xref: /petsc/src/ksp/pc/impls/fieldsplit/fieldsplit.c (revision a3df900d2f835f705491935f175b1610c348d9be)
1dba47a55SKris Buschelman 
2b45d2f2cSJed Brown #include <petsc-private/pcimpl.h>     /*I "petscpc.h" I*/
33c48a1e8SJed Brown #include <petscdmcomposite.h>   /*I "petscdmcomposite.h" I*/
40971522cSBarry Smith 
5f7c28744SJed Brown const char *const PCFieldSplitSchurPreTypes[] = {"SELF","DIAG","USER","PCFieldSplitSchurPreType","PC_FIELDSPLIT_SCHUR_PRE_",0};
6c9c6ffaaSJed Brown const char *const PCFieldSplitSchurFactTypes[] = {"DIAG","LOWER","UPPER","FULL","PCFieldSplitSchurFactType","PC_FIELDSPLIT_SCHUR_FACT_",0};
7c5d2311dSJed Brown 
80971522cSBarry Smith typedef struct _PC_FieldSplitLink *PC_FieldSplitLink;
90971522cSBarry Smith struct _PC_FieldSplitLink {
1069a612a9SBarry Smith   KSP               ksp;
110971522cSBarry Smith   Vec               x,y;
12db4c96c1SJed Brown   char              *splitname;
130971522cSBarry Smith   PetscInt          nfields;
145d4c12cdSJungho Lee   PetscInt          *fields,*fields_col;
151b9fc7fcSBarry Smith   VecScatter        sctx;
165d4c12cdSJungho Lee   IS                is,is_col;
1751f519a2SBarry Smith   PC_FieldSplitLink next,previous;
180971522cSBarry Smith };
190971522cSBarry Smith 
200971522cSBarry Smith typedef struct {
2168dd23aaSBarry Smith   PCCompositeType                    type;
22ace3abfcSBarry Smith   PetscBool                          defaultsplit; /* Flag for a system with a set of 'k' scalar fields with the same layout (and bs = k) */
23ace3abfcSBarry Smith   PetscBool                          splitdefined; /* Flag is set after the splits have been defined, to prevent more splits from being added */
24ace3abfcSBarry Smith   PetscBool                          realdiagonal; /* Flag to use the diagonal blocks of mat preconditioned by pmat, instead of just pmat */
2530ad9308SMatthew Knepley   PetscInt                           bs;           /* Block size for IS and Mat structures */
2630ad9308SMatthew Knepley   PetscInt                           nsplits;      /* Number of field divisions defined */
2779416396SBarry Smith   Vec                                *x,*y,w1,w2;
28519d70e2SJed Brown   Mat                                *mat;         /* The diagonal block for each split */
29519d70e2SJed Brown   Mat                                *pmat;        /* The preconditioning diagonal block for each split */
3030ad9308SMatthew Knepley   Mat                                *Afield;      /* The rows of the matrix associated with each split */
31ace3abfcSBarry Smith   PetscBool                          issetup;
3230ad9308SMatthew Knepley   /* Only used when Schur complement preconditioning is used */
3330ad9308SMatthew Knepley   Mat                                B;            /* The (0,1) block */
3430ad9308SMatthew Knepley   Mat                                C;            /* The (1,0) block */
35a04f6461SBarry Smith   Mat                                schur;        /* The Schur complement S = A11 - A10 A00^{-1} A01 */
36084e4875SJed Brown   Mat                                schur_user;   /* User-provided preconditioning matrix for the Schur complement */
37084e4875SJed Brown   PCFieldSplitSchurPreType           schurpre; /* Determines which preconditioning matrix is used for the Schur complement */
38c9c6ffaaSJed Brown   PCFieldSplitSchurFactType schurfactorization;
3930ad9308SMatthew Knepley   KSP                                kspschur;     /* The solver for S */
4097bbdb24SBarry Smith   PC_FieldSplitLink                  head;
4163ec74ffSBarry Smith   PetscBool                          reset;         /* indicates PCReset() has been last called on this object, hack */
42c1570756SJed Brown   PetscBool                          suboptionsset; /* Indicates that the KSPSetFromOptions() has been called on the sub-KSPs */
430971522cSBarry Smith } PC_FieldSplit;
440971522cSBarry Smith 
4516913363SBarry Smith /*
4616913363SBarry Smith     Notes: there is no particular reason that pmat, x, and y are stored as arrays in PC_FieldSplit instead of
4716913363SBarry Smith    inside PC_FieldSplitLink, just historical. If you want to be able to add new fields after already using the
4816913363SBarry Smith    PC you could change this.
4916913363SBarry Smith */
50084e4875SJed Brown 
51e6cab6aaSJed Brown /* This helper is so that setting a user-provided preconditioning matrix is orthogonal to choosing to use it.  This way the
52084e4875SJed Brown * application-provided FormJacobian can provide this matrix without interfering with the user's (command-line) choices. */
53084e4875SJed Brown static Mat FieldSplitSchurPre(PC_FieldSplit *jac)
54084e4875SJed Brown {
55084e4875SJed Brown   switch (jac->schurpre) {
56084e4875SJed Brown     case PC_FIELDSPLIT_SCHUR_PRE_SELF: return jac->schur;
57084e4875SJed Brown     case PC_FIELDSPLIT_SCHUR_PRE_DIAG: return jac->pmat[1];
58084e4875SJed Brown     case PC_FIELDSPLIT_SCHUR_PRE_USER: /* Use a user-provided matrix if it is given, otherwise diagonal block */
59084e4875SJed Brown     default:
60084e4875SJed Brown       return jac->schur_user ? jac->schur_user : jac->pmat[1];
61084e4875SJed Brown   }
62084e4875SJed Brown }
63084e4875SJed Brown 
64084e4875SJed Brown 
650971522cSBarry Smith #undef __FUNCT__
660971522cSBarry Smith #define __FUNCT__ "PCView_FieldSplit"
670971522cSBarry Smith static PetscErrorCode PCView_FieldSplit(PC pc,PetscViewer viewer)
680971522cSBarry Smith {
690971522cSBarry Smith   PC_FieldSplit     *jac = (PC_FieldSplit*)pc->data;
700971522cSBarry Smith   PetscErrorCode    ierr;
71ace3abfcSBarry Smith   PetscBool         iascii;
720971522cSBarry Smith   PetscInt          i,j;
735a9f2f41SSatish Balay   PC_FieldSplitLink ilink = jac->head;
740971522cSBarry Smith 
750971522cSBarry Smith   PetscFunctionBegin;
76251f4c67SDmitry Karpeev   ierr = PetscObjectTypeCompare((PetscObject)viewer,PETSCVIEWERASCII,&iascii);CHKERRQ(ierr);
770971522cSBarry Smith   if (iascii) {
782c9966d7SBarry Smith     if (jac->bs > 0) {
7951f519a2SBarry Smith       ierr = PetscViewerASCIIPrintf(viewer,"  FieldSplit with %s composition: total splits = %D, blocksize = %D\n",PCCompositeTypes[jac->type],jac->nsplits,jac->bs);CHKERRQ(ierr);
802c9966d7SBarry Smith     } else {
812c9966d7SBarry Smith       ierr = PetscViewerASCIIPrintf(viewer,"  FieldSplit with %s composition: total splits = %D\n",PCCompositeTypes[jac->type],jac->nsplits);CHKERRQ(ierr);
822c9966d7SBarry Smith     }
83*a3df900dSMatthew G Knepley     if (jac->realdiagonal) {
84*a3df900dSMatthew G Knepley       ierr = PetscViewerASCIIPrintf(viewer,"  using actual matrix for blocks rather than preconditioner matrix\n");CHKERRQ(ierr);
85*a3df900dSMatthew G Knepley     }
8669a612a9SBarry Smith     ierr = PetscViewerASCIIPrintf(viewer,"  Solver info for each split is in the following KSP objects:\n");CHKERRQ(ierr);
870971522cSBarry Smith     ierr = PetscViewerASCIIPushTab(viewer);CHKERRQ(ierr);
880971522cSBarry Smith     for (i=0; i<jac->nsplits; i++) {
891ab39975SBarry Smith       if (ilink->fields) {
900971522cSBarry Smith 	ierr = PetscViewerASCIIPrintf(viewer,"Split number %D Fields ",i);CHKERRQ(ierr);
9179416396SBarry Smith 	ierr = PetscViewerASCIIUseTabs(viewer,PETSC_FALSE);CHKERRQ(ierr);
925a9f2f41SSatish Balay 	for (j=0; j<ilink->nfields; j++) {
9379416396SBarry Smith 	  if (j > 0) {
9479416396SBarry Smith 	    ierr = PetscViewerASCIIPrintf(viewer,",");CHKERRQ(ierr);
9579416396SBarry Smith 	  }
965a9f2f41SSatish Balay 	  ierr = PetscViewerASCIIPrintf(viewer," %D",ilink->fields[j]);CHKERRQ(ierr);
970971522cSBarry Smith 	}
980971522cSBarry Smith 	ierr = PetscViewerASCIIPrintf(viewer,"\n");CHKERRQ(ierr);
9979416396SBarry Smith         ierr = PetscViewerASCIIUseTabs(viewer,PETSC_TRUE);CHKERRQ(ierr);
1001ab39975SBarry Smith       } else {
1011ab39975SBarry Smith 	ierr = PetscViewerASCIIPrintf(viewer,"Split number %D Defined by IS\n",i);CHKERRQ(ierr);
1021ab39975SBarry Smith       }
1035a9f2f41SSatish Balay       ierr = KSPView(ilink->ksp,viewer);CHKERRQ(ierr);
1045a9f2f41SSatish Balay       ilink = ilink->next;
1050971522cSBarry Smith     }
1060971522cSBarry Smith     ierr = PetscViewerASCIIPopTab(viewer);CHKERRQ(ierr);
1070971522cSBarry Smith   } else {
10865e19b50SBarry Smith     SETERRQ1(((PetscObject)pc)->comm,PETSC_ERR_SUP,"Viewer type %s not supported for PCFieldSplit",((PetscObject)viewer)->type_name);
1090971522cSBarry Smith   }
1100971522cSBarry Smith   PetscFunctionReturn(0);
1110971522cSBarry Smith }
1120971522cSBarry Smith 
1130971522cSBarry Smith #undef __FUNCT__
1143b224e63SBarry Smith #define __FUNCT__ "PCView_FieldSplit_Schur"
1153b224e63SBarry Smith static PetscErrorCode PCView_FieldSplit_Schur(PC pc,PetscViewer viewer)
1163b224e63SBarry Smith {
1173b224e63SBarry Smith   PC_FieldSplit     *jac = (PC_FieldSplit*)pc->data;
1183b224e63SBarry Smith   PetscErrorCode    ierr;
119ace3abfcSBarry Smith   PetscBool         iascii;
1203b224e63SBarry Smith   PetscInt          i,j;
1213b224e63SBarry Smith   PC_FieldSplitLink ilink = jac->head;
1223b224e63SBarry Smith   KSP               ksp;
1233b224e63SBarry Smith 
1243b224e63SBarry Smith   PetscFunctionBegin;
125251f4c67SDmitry Karpeev   ierr = PetscObjectTypeCompare((PetscObject)viewer,PETSCVIEWERASCII,&iascii);CHKERRQ(ierr);
1263b224e63SBarry Smith   if (iascii) {
1272c9966d7SBarry Smith     if (jac->bs > 0) {
128c9c6ffaaSJed Brown       ierr = PetscViewerASCIIPrintf(viewer,"  FieldSplit with Schur preconditioner, blocksize = %D, factorization %s\n",jac->bs,PCFieldSplitSchurFactTypes[jac->schurfactorization]);CHKERRQ(ierr);
1292c9966d7SBarry Smith     } else {
1302c9966d7SBarry Smith       ierr = PetscViewerASCIIPrintf(viewer,"  FieldSplit with Schur preconditioner, factorization %s\n",PCFieldSplitSchurFactTypes[jac->schurfactorization]);CHKERRQ(ierr);
1312c9966d7SBarry Smith     }
132*a3df900dSMatthew G Knepley     if (jac->realdiagonal) {
133*a3df900dSMatthew G Knepley       ierr = PetscViewerASCIIPrintf(viewer,"  using actual matrix for blocks rather than preconditioner matrix\n");CHKERRQ(ierr);
134*a3df900dSMatthew G Knepley     }
1353e8b8b31SMatthew G Knepley     switch(jac->schurpre) {
1363e8b8b31SMatthew G Knepley     case PC_FIELDSPLIT_SCHUR_PRE_SELF:
1373e8b8b31SMatthew G Knepley       ierr = PetscViewerASCIIPrintf(viewer,"  Preconditioner for the Schur complement formed from S itself\n");CHKERRQ(ierr);break;
138b02e2d75SMatthew G Knepley     case PC_FIELDSPLIT_SCHUR_PRE_DIAG:
1393e8b8b31SMatthew G Knepley       ierr = PetscViewerASCIIPrintf(viewer,"  Preconditioner for the Schur complement formed from the block diagonal part of A11\n");CHKERRQ(ierr);break;
1403e8b8b31SMatthew G Knepley     case PC_FIELDSPLIT_SCHUR_PRE_USER:
1413e8b8b31SMatthew G Knepley       if (jac->schur_user) {
1423e8b8b31SMatthew G Knepley         ierr = PetscViewerASCIIPrintf(viewer,"  Preconditioner for the Schur complement formed from user provided matrix\n");CHKERRQ(ierr);
1433e8b8b31SMatthew G Knepley       } else {
1443e8b8b31SMatthew G Knepley       ierr = PetscViewerASCIIPrintf(viewer,"  Preconditioner for the Schur complement formed from the block diagonal part of A11\n");CHKERRQ(ierr);
1453e8b8b31SMatthew G Knepley       }
1463e8b8b31SMatthew G Knepley       break;
1473e8b8b31SMatthew G Knepley     default:
1483e8b8b31SMatthew G Knepley       SETERRQ1(((PetscObject) pc)->comm, PETSC_ERR_ARG_OUTOFRANGE, "Invalid Schur preconditioning type: %d", jac->schurpre);
1493e8b8b31SMatthew G Knepley     }
1503b224e63SBarry Smith     ierr = PetscViewerASCIIPrintf(viewer,"  Split info:\n");CHKERRQ(ierr);
1513b224e63SBarry Smith     ierr = PetscViewerASCIIPushTab(viewer);CHKERRQ(ierr);
1523b224e63SBarry Smith     for (i=0; i<jac->nsplits; i++) {
1533b224e63SBarry Smith       if (ilink->fields) {
1543b224e63SBarry Smith 	ierr = PetscViewerASCIIPrintf(viewer,"Split number %D Fields ",i);CHKERRQ(ierr);
1553b224e63SBarry Smith 	ierr = PetscViewerASCIIUseTabs(viewer,PETSC_FALSE);CHKERRQ(ierr);
1563b224e63SBarry Smith 	for (j=0; j<ilink->nfields; j++) {
1573b224e63SBarry Smith 	  if (j > 0) {
1583b224e63SBarry Smith 	    ierr = PetscViewerASCIIPrintf(viewer,",");CHKERRQ(ierr);
1593b224e63SBarry Smith 	  }
1603b224e63SBarry Smith 	  ierr = PetscViewerASCIIPrintf(viewer," %D",ilink->fields[j]);CHKERRQ(ierr);
1613b224e63SBarry Smith 	}
1623b224e63SBarry Smith 	ierr = PetscViewerASCIIPrintf(viewer,"\n");CHKERRQ(ierr);
1633b224e63SBarry Smith         ierr = PetscViewerASCIIUseTabs(viewer,PETSC_TRUE);CHKERRQ(ierr);
1643b224e63SBarry Smith       } else {
1653b224e63SBarry Smith 	ierr = PetscViewerASCIIPrintf(viewer,"Split number %D Defined by IS\n",i);CHKERRQ(ierr);
1663b224e63SBarry Smith       }
1673b224e63SBarry Smith       ilink = ilink->next;
1683b224e63SBarry Smith     }
169435f959eSBarry Smith     ierr = PetscViewerASCIIPrintf(viewer,"KSP solver for A00 block \n");CHKERRQ(ierr);
1703b224e63SBarry Smith     ierr = PetscViewerASCIIPushTab(viewer);CHKERRQ(ierr);
17112cae6f2SJed Brown     if (jac->schur) {
17212cae6f2SJed Brown       ierr = MatSchurComplementGetKSP(jac->schur,&ksp);CHKERRQ(ierr);
1733b224e63SBarry Smith       ierr = KSPView(ksp,viewer);CHKERRQ(ierr);
17412cae6f2SJed Brown     } else {
17512cae6f2SJed Brown       ierr = PetscViewerASCIIPrintf(viewer,"  not yet available\n");CHKERRQ(ierr);
17612cae6f2SJed Brown     }
1773b224e63SBarry Smith     ierr = PetscViewerASCIIPopTab(viewer);CHKERRQ(ierr);
178435f959eSBarry Smith     ierr = PetscViewerASCIIPrintf(viewer,"KSP solver for S = A11 - A10 inv(A00) A01 \n");CHKERRQ(ierr);
1793b224e63SBarry Smith     ierr = PetscViewerASCIIPushTab(viewer);CHKERRQ(ierr);
18012cae6f2SJed Brown     if (jac->kspschur) {
1813b224e63SBarry Smith       ierr = KSPView(jac->kspschur,viewer);CHKERRQ(ierr);
18212cae6f2SJed Brown     } else {
18312cae6f2SJed Brown       ierr = PetscViewerASCIIPrintf(viewer,"  not yet available\n");CHKERRQ(ierr);
18412cae6f2SJed Brown     }
1853b224e63SBarry Smith     ierr = PetscViewerASCIIPopTab(viewer);CHKERRQ(ierr);
1863b224e63SBarry Smith     ierr = PetscViewerASCIIPopTab(viewer);CHKERRQ(ierr);
1873b224e63SBarry Smith   } else {
18865e19b50SBarry Smith     SETERRQ1(((PetscObject)pc)->comm,PETSC_ERR_SUP,"Viewer type %s not supported for PCFieldSplit",((PetscObject)viewer)->type_name);
1893b224e63SBarry Smith   }
1903b224e63SBarry Smith   PetscFunctionReturn(0);
1913b224e63SBarry Smith }
1923b224e63SBarry Smith 
1933b224e63SBarry Smith #undef __FUNCT__
1946c924f48SJed Brown #define __FUNCT__ "PCFieldSplitSetRuntimeSplits_Private"
1956c924f48SJed Brown /* Precondition: jac->bs is set to a meaningful value */
1966c924f48SJed Brown static PetscErrorCode PCFieldSplitSetRuntimeSplits_Private(PC pc)
1976c924f48SJed Brown {
1986c924f48SJed Brown   PetscErrorCode ierr;
1996c924f48SJed Brown   PC_FieldSplit  *jac = (PC_FieldSplit*)pc->data;
2005d4c12cdSJungho Lee   PetscInt       i,nfields,*ifields,nfields_col,*ifields_col;
2015d4c12cdSJungho Lee   PetscBool      flg,flg_col;
2025d4c12cdSJungho Lee   char           optionname[128],splitname[8],optionname_col[128];
2036c924f48SJed Brown 
2046c924f48SJed Brown   PetscFunctionBegin;
2056c924f48SJed Brown   ierr = PetscMalloc(jac->bs*sizeof(PetscInt),&ifields);CHKERRQ(ierr);
2065d4c12cdSJungho Lee   ierr = PetscMalloc(jac->bs*sizeof(PetscInt),&ifields_col);CHKERRQ(ierr);
2076c924f48SJed Brown   for (i=0,flg=PETSC_TRUE; ; i++) {
2086c924f48SJed Brown     ierr = PetscSNPrintf(splitname,sizeof splitname,"%D",i);CHKERRQ(ierr);
2096c924f48SJed Brown     ierr = PetscSNPrintf(optionname,sizeof optionname,"-pc_fieldsplit_%D_fields",i);CHKERRQ(ierr);
2105d4c12cdSJungho Lee     ierr = PetscSNPrintf(optionname_col,sizeof optionname_col,"-pc_fieldsplit_%D_fields_col",i);CHKERRQ(ierr);
2116c924f48SJed Brown     nfields = jac->bs;
21229499fbbSJungho Lee     nfields_col = jac->bs;
2136c924f48SJed Brown     ierr    = PetscOptionsGetIntArray(((PetscObject)pc)->prefix,optionname,ifields,&nfields,&flg);CHKERRQ(ierr);
2145d4c12cdSJungho Lee     ierr    = PetscOptionsGetIntArray(((PetscObject)pc)->prefix,optionname_col,ifields_col,&nfields_col,&flg_col);CHKERRQ(ierr);
2156c924f48SJed Brown     if (!flg) break;
2165d4c12cdSJungho Lee     else if (flg && !flg_col) {
2175d4c12cdSJungho Lee       if (!nfields) SETERRQ(PETSC_COMM_SELF,PETSC_ERR_USER,"Cannot list zero fields");
2185d4c12cdSJungho Lee       ierr = PCFieldSplitSetFields(pc,splitname,nfields,ifields,ifields);CHKERRQ(ierr);
2195d4c12cdSJungho Lee     }
2205d4c12cdSJungho Lee     else {
2215d4c12cdSJungho Lee       if (!nfields || !nfields_col) SETERRQ(PETSC_COMM_SELF,PETSC_ERR_USER,"Cannot list zero fields");
2225d4c12cdSJungho Lee       if (nfields != nfields_col) SETERRQ(PETSC_COMM_SELF,PETSC_ERR_USER,"Number of row and column fields must match");
2235d4c12cdSJungho Lee       ierr = PCFieldSplitSetFields(pc,splitname,nfields,ifields,ifields_col);CHKERRQ(ierr);
2245d4c12cdSJungho Lee     }
2256c924f48SJed Brown   }
2266c924f48SJed Brown   if (i > 0) {
2276c924f48SJed Brown     /* Makes command-line setting of splits take precedence over setting them in code.
2286c924f48SJed Brown        Otherwise subsequent calls to PCFieldSplitSetIS() or PCFieldSplitSetFields() would
2296c924f48SJed Brown        create new splits, which would probably not be what the user wanted. */
2306c924f48SJed Brown     jac->splitdefined = PETSC_TRUE;
2316c924f48SJed Brown   }
2326c924f48SJed Brown   ierr = PetscFree(ifields);CHKERRQ(ierr);
2335d4c12cdSJungho Lee   ierr = PetscFree(ifields_col);CHKERRQ(ierr);
2346c924f48SJed Brown   PetscFunctionReturn(0);
2356c924f48SJed Brown }
2366c924f48SJed Brown 
2376c924f48SJed Brown #undef __FUNCT__
23869a612a9SBarry Smith #define __FUNCT__ "PCFieldSplitSetDefaults"
23969a612a9SBarry Smith static PetscErrorCode PCFieldSplitSetDefaults(PC pc)
2400971522cSBarry Smith {
2410971522cSBarry Smith   PC_FieldSplit     *jac  = (PC_FieldSplit*)pc->data;
2420971522cSBarry Smith   PetscErrorCode    ierr;
2435a9f2f41SSatish Balay   PC_FieldSplitLink ilink = jac->head;
2446ce1633cSBarry Smith   PetscBool         flg = PETSC_FALSE,stokes = PETSC_FALSE;
2456c924f48SJed Brown   PetscInt          i;
2460971522cSBarry Smith 
2470971522cSBarry Smith   PetscFunctionBegin;
248d32f9abdSBarry Smith   if (!ilink) {
249d0af7cd3SBarry Smith     ierr = PetscOptionsGetBool(((PetscObject)pc)->prefix,"-pc_fieldsplit_detect_saddle_point",&stokes,PETSC_NULL);CHKERRQ(ierr);
250d0af7cd3SBarry Smith     if (pc->dm && !stokes) {
2517b62db95SJungho Lee       PetscInt     numFields, f;
2520784a22cSJed Brown       char         **fieldNames;
2537b62db95SJungho Lee       IS          *fields;
254e7c4fc90SDmitry Karpeev       DM          *dms;
255e7c4fc90SDmitry Karpeev       ierr = DMCreateDecomposition(pc->dm, &numFields, &fieldNames, &fields, &dms);    CHKERRQ(ierr);
2567b62db95SJungho Lee       for(f = 0; f < numFields; ++f) {
2577b62db95SJungho Lee         ierr = PCFieldSplitSetIS(pc, fieldNames[f], fields[f]);CHKERRQ(ierr);
2587b62db95SJungho Lee         ierr = PetscFree(fieldNames[f]);CHKERRQ(ierr);
2597b62db95SJungho Lee         ierr = ISDestroy(&fields[f]);CHKERRQ(ierr);
2607b62db95SJungho Lee       }
2617b62db95SJungho Lee       ierr = PetscFree(fieldNames);CHKERRQ(ierr);
2627b62db95SJungho Lee       ierr = PetscFree(fields);CHKERRQ(ierr);
263e7c4fc90SDmitry Karpeev       if(dms) {
2648b8307b2SJed Brown         ierr = PetscInfo(pc,"Setting up physics based fieldsplit preconditioner using the embedded DM\n");CHKERRQ(ierr);
2657b62db95SJungho Lee         for (ilink=jac->head,i=0; ilink; ilink=ilink->next,i++) {
2667b62db95SJungho Lee           ierr = KSPSetDM(ilink->ksp, dms[i]);CHKERRQ(ierr);
2677b62db95SJungho Lee           ierr = KSPSetDMActive(ilink->ksp, PETSC_FALSE);CHKERRQ(ierr);
268e7c4fc90SDmitry Karpeev           ierr = DMDestroy(&dms[i]); CHKERRQ(ierr);
2692fa5ba8aSJed Brown         }
2707b62db95SJungho Lee         ierr = PetscFree(dms);CHKERRQ(ierr);
2718b8307b2SJed Brown       }
27266ffff09SJed Brown     } else {
273521d7252SBarry Smith       if (jac->bs <= 0) {
274704ba839SBarry Smith         if (pc->pmat) {
275521d7252SBarry Smith           ierr   = MatGetBlockSize(pc->pmat,&jac->bs);CHKERRQ(ierr);
276704ba839SBarry Smith         } else {
277704ba839SBarry Smith           jac->bs = 1;
278704ba839SBarry Smith         }
279521d7252SBarry Smith       }
280d32f9abdSBarry Smith 
281acfcf0e5SJed Brown       ierr = PetscOptionsGetBool(((PetscObject)pc)->prefix,"-pc_fieldsplit_default",&flg,PETSC_NULL);CHKERRQ(ierr);
2826ce1633cSBarry Smith       if (stokes) {
2836ce1633cSBarry Smith         IS       zerodiags,rest;
2846ce1633cSBarry Smith         PetscInt nmin,nmax;
2856ce1633cSBarry Smith 
2866ce1633cSBarry Smith         ierr = MatGetOwnershipRange(pc->mat,&nmin,&nmax);CHKERRQ(ierr);
2876ce1633cSBarry Smith         ierr = MatFindZeroDiagonals(pc->mat,&zerodiags);CHKERRQ(ierr);
2886ce1633cSBarry Smith         ierr = ISComplement(zerodiags,nmin,nmax,&rest);CHKERRQ(ierr);
2896ce1633cSBarry Smith         ierr = PCFieldSplitSetIS(pc,"0",rest);CHKERRQ(ierr);
2906ce1633cSBarry Smith         ierr = PCFieldSplitSetIS(pc,"1",zerodiags);CHKERRQ(ierr);
291fcfd50ebSBarry Smith         ierr = ISDestroy(&zerodiags);CHKERRQ(ierr);
292fcfd50ebSBarry Smith         ierr = ISDestroy(&rest);CHKERRQ(ierr);
2936ce1633cSBarry Smith       } else {
294d32f9abdSBarry Smith         if (!flg) {
295d32f9abdSBarry Smith           /* Allow user to set fields from command line,  if bs was known at the time of PCSetFromOptions_FieldSplit()
296d32f9abdSBarry Smith            then it is set there. This is not ideal because we should only have options set in XXSetFromOptions(). */
2976c924f48SJed Brown           ierr = PCFieldSplitSetRuntimeSplits_Private(pc);CHKERRQ(ierr);
2986c924f48SJed Brown           if (jac->splitdefined) {ierr = PetscInfo(pc,"Splits defined using the options database\n");CHKERRQ(ierr);}
299d32f9abdSBarry Smith         }
3006c924f48SJed Brown         if (flg || !jac->splitdefined) {
301d32f9abdSBarry Smith           ierr = PetscInfo(pc,"Using default splitting of fields\n");CHKERRQ(ierr);
302db4c96c1SJed Brown           for (i=0; i<jac->bs; i++) {
3036c924f48SJed Brown             char splitname[8];
3046c924f48SJed Brown             ierr = PetscSNPrintf(splitname,sizeof splitname,"%D",i);CHKERRQ(ierr);
3055d4c12cdSJungho Lee             ierr = PCFieldSplitSetFields(pc,splitname,1,&i,&i);CHKERRQ(ierr);
30679416396SBarry Smith           }
3075d4c12cdSJungho Lee           jac->defaultsplit = PETSC_TRUE;
308521d7252SBarry Smith         }
30966ffff09SJed Brown       }
3106ce1633cSBarry Smith     }
311edf189efSBarry Smith   } else if (jac->nsplits == 1) {
312edf189efSBarry Smith     if (ilink->is) {
313edf189efSBarry Smith       IS       is2;
314edf189efSBarry Smith       PetscInt nmin,nmax;
315edf189efSBarry Smith 
316edf189efSBarry Smith       ierr = MatGetOwnershipRange(pc->mat,&nmin,&nmax);CHKERRQ(ierr);
317edf189efSBarry Smith       ierr = ISComplement(ilink->is,nmin,nmax,&is2);CHKERRQ(ierr);
318db4c96c1SJed Brown       ierr = PCFieldSplitSetIS(pc,"1",is2);CHKERRQ(ierr);
319fcfd50ebSBarry Smith       ierr = ISDestroy(&is2);CHKERRQ(ierr);
3207b62db95SJungho Lee     } else SETERRQ(((PetscObject) pc)->comm,PETSC_ERR_SUP,"Must provide at least two sets of fields to PCFieldSplit()");
32163ec74ffSBarry Smith   } else if (jac->reset) {
32263ec74ffSBarry Smith     /* PCReset() has been called on this PC, ilink exists but all IS and Vec data structures in it must be rebuilt
323d0af7cd3SBarry Smith        This is basically the !ilink portion of code above copied from above and the allocation of the ilinks removed
324d0af7cd3SBarry Smith        since they already exist. This should be totally rewritten */
325d0af7cd3SBarry Smith     ierr = PetscOptionsGetBool(((PetscObject)pc)->prefix,"-pc_fieldsplit_detect_saddle_point",&stokes,PETSC_NULL);CHKERRQ(ierr);
326d0af7cd3SBarry Smith     if (pc->dm && !stokes) {
327d0af7cd3SBarry Smith       PetscBool dmcomposite;
328251f4c67SDmitry Karpeev       ierr = PetscObjectTypeCompare((PetscObject)pc->dm,DMCOMPOSITE,&dmcomposite);CHKERRQ(ierr);
329d0af7cd3SBarry Smith       if (dmcomposite) {
330d0af7cd3SBarry Smith         PetscInt nDM;
331d0af7cd3SBarry Smith         IS       *fields;
3327b62db95SJungho Lee         DM       *dms;
333d0af7cd3SBarry Smith         ierr = PetscInfo(pc,"Setting up physics based fieldsplit preconditioner using the embedded DM\n");CHKERRQ(ierr);
334d0af7cd3SBarry Smith         ierr = DMCompositeGetNumberDM(pc->dm,&nDM);CHKERRQ(ierr);
335d0af7cd3SBarry Smith         ierr = DMCompositeGetGlobalISs(pc->dm,&fields);CHKERRQ(ierr);
3367b62db95SJungho Lee         ierr = PetscMalloc(nDM*sizeof(DM),&dms);CHKERRQ(ierr);
3377b62db95SJungho Lee         ierr = DMCompositeGetEntriesArray(pc->dm,dms);CHKERRQ(ierr);
338d0af7cd3SBarry Smith         for (i=0; i<nDM; i++) {
3397b62db95SJungho Lee           ierr = KSPSetDM(ilink->ksp,dms[i]);CHKERRQ(ierr);
3407b62db95SJungho Lee           ierr = KSPSetDMActive(ilink->ksp,PETSC_FALSE);CHKERRQ(ierr);
341d0af7cd3SBarry Smith           ilink->is = fields[i];
342d0af7cd3SBarry Smith           ilink     = ilink->next;
343edf189efSBarry Smith         }
344d0af7cd3SBarry Smith         ierr = PetscFree(fields);CHKERRQ(ierr);
3457b62db95SJungho Lee         ierr = PetscFree(dms);CHKERRQ(ierr);
346d0af7cd3SBarry Smith       }
347d0af7cd3SBarry Smith     } else {
348d0af7cd3SBarry Smith       ierr = PetscOptionsGetBool(((PetscObject)pc)->prefix,"-pc_fieldsplit_default",&flg,PETSC_NULL);CHKERRQ(ierr);
349d0af7cd3SBarry Smith       if (stokes) {
350d0af7cd3SBarry Smith         IS       zerodiags,rest;
351d0af7cd3SBarry Smith         PetscInt nmin,nmax;
352d0af7cd3SBarry Smith 
353d0af7cd3SBarry Smith         ierr = MatGetOwnershipRange(pc->mat,&nmin,&nmax);CHKERRQ(ierr);
354d0af7cd3SBarry Smith         ierr = MatFindZeroDiagonals(pc->mat,&zerodiags);CHKERRQ(ierr);
355d0af7cd3SBarry Smith         ierr = ISComplement(zerodiags,nmin,nmax,&rest);CHKERRQ(ierr);
35620b26d62SBarry Smith         ierr = ISDestroy(&ilink->is);CHKERRQ(ierr);
35720b26d62SBarry Smith         ierr = ISDestroy(&ilink->next->is);CHKERRQ(ierr);
358d0af7cd3SBarry Smith         ilink->is       = rest;
359d0af7cd3SBarry Smith         ilink->next->is = zerodiags;
36020b26d62SBarry Smith       } else SETERRQ(((PetscObject)pc)->comm,PETSC_ERR_SUP,"Cases not yet handled when PCReset() was used");
361d0af7cd3SBarry Smith     }
362d0af7cd3SBarry Smith   }
363d0af7cd3SBarry Smith 
3647b62db95SJungho Lee   if (jac->nsplits < 2) SETERRQ1(((PetscObject) pc)->comm,PETSC_ERR_PLIB,"Unhandled case, must have at least two fields, not %d", jac->nsplits);
36569a612a9SBarry Smith   PetscFunctionReturn(0);
36669a612a9SBarry Smith }
36769a612a9SBarry Smith 
36869a612a9SBarry Smith #undef __FUNCT__
36969a612a9SBarry Smith #define __FUNCT__ "PCSetUp_FieldSplit"
37069a612a9SBarry Smith static PetscErrorCode PCSetUp_FieldSplit(PC pc)
37169a612a9SBarry Smith {
37269a612a9SBarry Smith   PC_FieldSplit     *jac = (PC_FieldSplit*)pc->data;
37369a612a9SBarry Smith   PetscErrorCode    ierr;
3745a9f2f41SSatish Balay   PC_FieldSplitLink ilink;
3752c9966d7SBarry Smith   PetscInt          i,nsplit;
37669a612a9SBarry Smith   MatStructure      flag = pc->flag;
3775f4ab4e1SJungho Lee   PetscBool         sorted, sorted_col;
37869a612a9SBarry Smith 
37969a612a9SBarry Smith   PetscFunctionBegin;
38069a612a9SBarry Smith   ierr   = PCFieldSplitSetDefaults(pc);CHKERRQ(ierr);
38197bbdb24SBarry Smith   nsplit = jac->nsplits;
3825a9f2f41SSatish Balay   ilink  = jac->head;
38397bbdb24SBarry Smith 
38497bbdb24SBarry Smith   /* get the matrices for each split */
385704ba839SBarry Smith   if (!jac->issetup) {
3861b9fc7fcSBarry Smith     PetscInt rstart,rend,nslots,bs;
38797bbdb24SBarry Smith 
388704ba839SBarry Smith     jac->issetup = PETSC_TRUE;
389704ba839SBarry Smith 
3905d4c12cdSJungho Lee     /* This is done here instead of in PCFieldSplitSetFields() because may not have matrix at that point */
3912c9966d7SBarry Smith     if (jac->defaultsplit || !ilink->is) {
3922c9966d7SBarry Smith       if (jac->bs <= 0) jac->bs = nsplit;
3932c9966d7SBarry Smith     }
39451f519a2SBarry Smith     bs     = jac->bs;
39597bbdb24SBarry Smith     ierr   = MatGetOwnershipRange(pc->pmat,&rstart,&rend);CHKERRQ(ierr);
3961b9fc7fcSBarry Smith     nslots = (rend - rstart)/bs;
3971b9fc7fcSBarry Smith     for (i=0; i<nsplit; i++) {
3981b9fc7fcSBarry Smith       if (jac->defaultsplit) {
399704ba839SBarry Smith         ierr = ISCreateStride(((PetscObject)pc)->comm,nslots,rstart+i,nsplit,&ilink->is);CHKERRQ(ierr);
4005f4ab4e1SJungho Lee         ierr = ISDuplicate(ilink->is,&ilink->is_col);CHKERRQ(ierr);
401704ba839SBarry Smith       } else if (!ilink->is) {
402ccb205f8SBarry Smith         if (ilink->nfields > 1) {
4035f4ab4e1SJungho Lee           PetscInt   *ii,*jj,j,k,nfields = ilink->nfields,*fields = ilink->fields,*fields_col = ilink->fields_col;
4045a9f2f41SSatish Balay           ierr = PetscMalloc(ilink->nfields*nslots*sizeof(PetscInt),&ii);CHKERRQ(ierr);
4055f4ab4e1SJungho Lee           ierr = PetscMalloc(ilink->nfields*nslots*sizeof(PetscInt),&jj);CHKERRQ(ierr);
4061b9fc7fcSBarry Smith           for (j=0; j<nslots; j++) {
4071b9fc7fcSBarry Smith             for (k=0; k<nfields; k++) {
4081b9fc7fcSBarry Smith               ii[nfields*j + k] = rstart + bs*j + fields[k];
4095f4ab4e1SJungho Lee               jj[nfields*j + k] = rstart + bs*j + fields_col[k];
41097bbdb24SBarry Smith             }
41197bbdb24SBarry Smith           }
412d67e408aSBarry Smith           ierr = ISCreateGeneral(((PetscObject)pc)->comm,nslots*nfields,ii,PETSC_OWN_POINTER,&ilink->is);CHKERRQ(ierr);
4135f4ab4e1SJungho Lee           ierr = ISCreateGeneral(((PetscObject)pc)->comm,nslots*nfields,jj,PETSC_OWN_POINTER,&ilink->is_col);CHKERRQ(ierr);
414ccb205f8SBarry Smith         } else {
415704ba839SBarry Smith           ierr = ISCreateStride(((PetscObject)pc)->comm,nslots,rstart+ilink->fields[0],bs,&ilink->is);CHKERRQ(ierr);
4165f4ab4e1SJungho Lee           ierr = ISCreateStride(((PetscObject)pc)->comm,nslots,rstart+ilink->fields_col[0],bs,&ilink->is_col);CHKERRQ(ierr);
417ccb205f8SBarry Smith        }
4183e197d65SBarry Smith       }
419704ba839SBarry Smith       ierr = ISSorted(ilink->is,&sorted);CHKERRQ(ierr);
4205f4ab4e1SJungho Lee       if (ilink->is_col) { ierr = ISSorted(ilink->is_col,&sorted_col);CHKERRQ(ierr); }
4215f4ab4e1SJungho Lee       if (!sorted || !sorted_col) SETERRQ(PETSC_COMM_SELF,PETSC_ERR_USER,"Fields must be sorted when creating split");
422704ba839SBarry Smith       ilink = ilink->next;
4231b9fc7fcSBarry Smith     }
4241b9fc7fcSBarry Smith   }
4251b9fc7fcSBarry Smith 
426704ba839SBarry Smith   ilink  = jac->head;
42797bbdb24SBarry Smith   if (!jac->pmat) {
428bdddcaaaSMatthew G Knepley     Vec xtmp;
429bdddcaaaSMatthew G Knepley 
430bdddcaaaSMatthew G Knepley     ierr = MatGetVecs(pc->pmat,&xtmp,PETSC_NULL);CHKERRQ(ierr);
431cf502942SBarry Smith     ierr = PetscMalloc(nsplit*sizeof(Mat),&jac->pmat);CHKERRQ(ierr);
432bdddcaaaSMatthew G Knepley     ierr = PetscMalloc2(nsplit,Vec,&jac->x,nsplit,Vec,&jac->y);CHKERRQ(ierr);
433cf502942SBarry Smith     for (i=0; i<nsplit; i++) {
434bdddcaaaSMatthew G Knepley       MatNullSpace sp;
435bdddcaaaSMatthew G Knepley 
436*a3df900dSMatthew G Knepley       /* Check for preconditioning matrix attached to IS */
437*a3df900dSMatthew G Knepley       ierr = PetscObjectQuery((PetscObject) ilink->is, "pmat", (PetscObject *) &jac->pmat[i]);CHKERRQ(ierr);
438*a3df900dSMatthew G Knepley       if (jac->pmat[i]) {
439*a3df900dSMatthew G Knepley         ierr = PetscObjectReference((PetscObject) jac->pmat[i]);CHKERRQ(ierr);
440*a3df900dSMatthew G Knepley         if (jac->type == PC_COMPOSITE_SCHUR) {
441*a3df900dSMatthew G Knepley           jac->schur_user = jac->pmat[i];
442*a3df900dSMatthew G Knepley           ierr = PetscObjectReference((PetscObject) jac->schur_user);CHKERRQ(ierr);
443*a3df900dSMatthew G Knepley         }
444*a3df900dSMatthew G Knepley       } else {
4455f4ab4e1SJungho Lee         ierr = MatGetSubMatrix(pc->pmat,ilink->is,ilink->is_col,MAT_INITIAL_MATRIX,&jac->pmat[i]);CHKERRQ(ierr);
446*a3df900dSMatthew G Knepley       }
447bdddcaaaSMatthew G Knepley       /* create work vectors for each split */
448bdddcaaaSMatthew G Knepley       ierr = MatGetVecs(jac->pmat[i],&jac->x[i],&jac->y[i]);CHKERRQ(ierr);
449bdddcaaaSMatthew G Knepley       ilink->x = jac->x[i]; ilink->y = jac->y[i];
450bdddcaaaSMatthew G Knepley       /* compute scatter contexts needed by multiplicative versions and non-default splits */
451bdddcaaaSMatthew G Knepley       ierr = VecScatterCreate(xtmp,ilink->is,jac->x[i],PETSC_NULL,&ilink->sctx);CHKERRQ(ierr);
452bdddcaaaSMatthew G Knepley       /* HACK: Check for the constant null space */
453bdddcaaaSMatthew G Knepley       ierr = MatGetNullSpace(pc->pmat, &sp);CHKERRQ(ierr);
454bdddcaaaSMatthew G Knepley       if (sp) {
455bdddcaaaSMatthew G Knepley         MatNullSpace subsp;
456bdddcaaaSMatthew G Knepley         Vec          ftmp, gtmp;
4579583d628SBarry Smith         PetscReal    norm;
458bdddcaaaSMatthew G Knepley         PetscInt     N;
459bdddcaaaSMatthew G Knepley 
460bdddcaaaSMatthew G Knepley         ierr = MatGetVecs(pc->pmat,     &gtmp, PETSC_NULL);CHKERRQ(ierr);
461bdddcaaaSMatthew G Knepley         ierr = MatGetVecs(jac->pmat[i], &ftmp, PETSC_NULL);CHKERRQ(ierr);
462bdddcaaaSMatthew G Knepley         ierr = VecGetSize(ftmp, &N);CHKERRQ(ierr);
463bdddcaaaSMatthew G Knepley         ierr = VecSet(ftmp, 1.0/N);CHKERRQ(ierr);
464bdddcaaaSMatthew G Knepley         ierr = VecScatterBegin(ilink->sctx, ftmp, gtmp, INSERT_VALUES, SCATTER_REVERSE);CHKERRQ(ierr);
465bdddcaaaSMatthew G Knepley         ierr = VecScatterEnd(ilink->sctx, ftmp, gtmp, INSERT_VALUES, SCATTER_REVERSE);CHKERRQ(ierr);
466bdddcaaaSMatthew G Knepley         ierr = MatNullSpaceRemove(sp, gtmp, PETSC_NULL);CHKERRQ(ierr);
467bdddcaaaSMatthew G Knepley         ierr = VecNorm(gtmp, NORM_2, &norm);CHKERRQ(ierr);
468bdddcaaaSMatthew G Knepley         if (norm < 1.0e-10) {
469bdddcaaaSMatthew G Knepley           ierr  = MatNullSpaceCreate(((PetscObject)pc)->comm, PETSC_TRUE, 0, PETSC_NULL, &subsp);CHKERRQ(ierr);
470bdddcaaaSMatthew G Knepley           ierr  = MatSetNullSpace(jac->pmat[i], subsp);CHKERRQ(ierr);
471bdddcaaaSMatthew G Knepley           ierr  = MatNullSpaceDestroy(&subsp);CHKERRQ(ierr);
472bdddcaaaSMatthew G Knepley         }
473bdddcaaaSMatthew G Knepley         ierr = VecDestroy(&ftmp);CHKERRQ(ierr);
474bdddcaaaSMatthew G Knepley         ierr = VecDestroy(&gtmp);CHKERRQ(ierr);
475bdddcaaaSMatthew G Knepley       }
476ed1f0337SMatthew G Knepley       /* Check for null space attached to IS */
477ed1f0337SMatthew G Knepley       ierr = PetscObjectQuery((PetscObject) ilink->is, "nearnullspace", (PetscObject *) &sp);CHKERRQ(ierr);
478ed1f0337SMatthew G Knepley       if (sp) {
479ed1f0337SMatthew G Knepley         ierr  = MatSetNearNullSpace(jac->pmat[i], sp);CHKERRQ(ierr);
480ed1f0337SMatthew G Knepley       }
481704ba839SBarry Smith       ilink = ilink->next;
482cf502942SBarry Smith     }
483bdddcaaaSMatthew G Knepley     ierr = VecDestroy(&xtmp);CHKERRQ(ierr);
48497bbdb24SBarry Smith   } else {
485cf502942SBarry Smith     for (i=0; i<nsplit; i++) {
486*a3df900dSMatthew G Knepley       Mat pmat;
487*a3df900dSMatthew G Knepley 
488*a3df900dSMatthew G Knepley       /* Check for preconditioning matrix attached to IS */
489*a3df900dSMatthew G Knepley       ierr = PetscObjectQuery((PetscObject) ilink->is, "pmat", (PetscObject *) &pmat);CHKERRQ(ierr);
490*a3df900dSMatthew G Knepley       if (!pmat) {
4915f4ab4e1SJungho Lee         ierr = MatGetSubMatrix(pc->pmat,ilink->is,ilink->is_col,MAT_REUSE_MATRIX,&jac->pmat[i]);CHKERRQ(ierr);
492*a3df900dSMatthew G Knepley       }
493704ba839SBarry Smith       ilink = ilink->next;
494cf502942SBarry Smith     }
49597bbdb24SBarry Smith   }
496519d70e2SJed Brown   if (jac->realdiagonal) {
497519d70e2SJed Brown     ilink = jac->head;
498519d70e2SJed Brown     if (!jac->mat) {
499519d70e2SJed Brown       ierr = PetscMalloc(nsplit*sizeof(Mat),&jac->mat);CHKERRQ(ierr);
500519d70e2SJed Brown       for (i=0; i<nsplit; i++) {
5015f4ab4e1SJungho Lee         ierr = MatGetSubMatrix(pc->mat,ilink->is,ilink->is_col,MAT_INITIAL_MATRIX,&jac->mat[i]);CHKERRQ(ierr);
502519d70e2SJed Brown         ilink = ilink->next;
503519d70e2SJed Brown       }
504519d70e2SJed Brown     } else {
505519d70e2SJed Brown       for (i=0; i<nsplit; i++) {
5065f4ab4e1SJungho Lee         if (jac->mat[i]) {ierr = MatGetSubMatrix(pc->mat,ilink->is,ilink->is_col,MAT_REUSE_MATRIX,&jac->mat[i]);CHKERRQ(ierr);}
507519d70e2SJed Brown         ilink = ilink->next;
508519d70e2SJed Brown       }
509519d70e2SJed Brown     }
510519d70e2SJed Brown   } else {
511519d70e2SJed Brown     jac->mat = jac->pmat;
512519d70e2SJed Brown   }
51397bbdb24SBarry Smith 
5146c8605c2SJed Brown   if (jac->type != PC_COMPOSITE_ADDITIVE  && jac->type != PC_COMPOSITE_SCHUR) {
51568dd23aaSBarry Smith     /* extract the rows of the matrix associated with each field: used for efficient computation of residual inside algorithm */
51668dd23aaSBarry Smith     ilink  = jac->head;
51768dd23aaSBarry Smith     if (!jac->Afield) {
51868dd23aaSBarry Smith       ierr = PetscMalloc(nsplit*sizeof(Mat),&jac->Afield);CHKERRQ(ierr);
51968dd23aaSBarry Smith       for (i=0; i<nsplit; i++) {
5204aa3045dSJed Brown         ierr = MatGetSubMatrix(pc->mat,ilink->is,PETSC_NULL,MAT_INITIAL_MATRIX,&jac->Afield[i]);CHKERRQ(ierr);
52168dd23aaSBarry Smith         ilink = ilink->next;
52268dd23aaSBarry Smith       }
52368dd23aaSBarry Smith     } else {
52468dd23aaSBarry Smith       for (i=0; i<nsplit; i++) {
5254aa3045dSJed Brown         ierr = MatGetSubMatrix(pc->mat,ilink->is,PETSC_NULL,MAT_REUSE_MATRIX,&jac->Afield[i]);CHKERRQ(ierr);
52668dd23aaSBarry Smith         ilink = ilink->next;
52768dd23aaSBarry Smith       }
52868dd23aaSBarry Smith     }
52968dd23aaSBarry Smith   }
53068dd23aaSBarry Smith 
5313b224e63SBarry Smith   if (jac->type == PC_COMPOSITE_SCHUR) {
5323b224e63SBarry Smith     IS       ccis;
5334aa3045dSJed Brown     PetscInt rstart,rend;
534093c86ffSJed Brown     char     lscname[256];
535093c86ffSJed Brown     PetscObject LSC_L;
536e7e72b3dSBarry Smith     if (nsplit != 2) SETERRQ(((PetscObject)pc)->comm,PETSC_ERR_ARG_INCOMP,"To use Schur complement preconditioner you must have exactly 2 fields");
53768dd23aaSBarry Smith 
538e6cab6aaSJed Brown     /* When extracting off-diagonal submatrices, we take complements from this range */
539e6cab6aaSJed Brown     ierr  = MatGetOwnershipRangeColumn(pc->mat,&rstart,&rend);CHKERRQ(ierr);
540e6cab6aaSJed Brown 
5413b224e63SBarry Smith     /* need to handle case when one is resetting up the preconditioner */
5423b224e63SBarry Smith     if (jac->schur) {
5433b224e63SBarry Smith       ilink = jac->head;
54449bb4cd7SJungho Lee       ierr  = ISComplement(ilink->is_col,rstart,rend,&ccis);CHKERRQ(ierr);
5454aa3045dSJed Brown       ierr  = MatGetSubMatrix(pc->mat,ilink->is,ccis,MAT_REUSE_MATRIX,&jac->B);CHKERRQ(ierr);
546fcfd50ebSBarry Smith       ierr  = ISDestroy(&ccis);CHKERRQ(ierr);
5473b224e63SBarry Smith       ilink = ilink->next;
54849bb4cd7SJungho Lee       ierr  = ISComplement(ilink->is_col,rstart,rend,&ccis);CHKERRQ(ierr);
5494aa3045dSJed Brown       ierr  = MatGetSubMatrix(pc->mat,ilink->is,ccis,MAT_REUSE_MATRIX,&jac->C);CHKERRQ(ierr);
550fcfd50ebSBarry Smith       ierr  = ISDestroy(&ccis);CHKERRQ(ierr);
551*a3df900dSMatthew G Knepley       ierr  = MatSchurComplementUpdate(jac->schur,jac->mat[0],jac->pmat[0],jac->B,jac->C,jac->mat[1],pc->flag);CHKERRQ(ierr);
552084e4875SJed Brown       ierr  = KSPSetOperators(jac->kspschur,jac->schur,FieldSplitSchurPre(jac),pc->flag);CHKERRQ(ierr);
5533b224e63SBarry Smith 
5543b224e63SBarry Smith      } else {
5551cee3971SBarry Smith       KSP ksp;
5566c924f48SJed Brown       char schurprefix[256];
557bdddcaaaSMatthew G Knepley       MatNullSpace sp;
5583b224e63SBarry Smith 
559a04f6461SBarry Smith       /* extract the A01 and A10 matrices */
5603b224e63SBarry Smith       ilink = jac->head;
56149bb4cd7SJungho Lee       ierr  = ISComplement(ilink->is_col,rstart,rend,&ccis);CHKERRQ(ierr);
5624aa3045dSJed Brown       ierr  = MatGetSubMatrix(pc->mat,ilink->is,ccis,MAT_INITIAL_MATRIX,&jac->B);CHKERRQ(ierr);
563fcfd50ebSBarry Smith       ierr  = ISDestroy(&ccis);CHKERRQ(ierr);
5643b224e63SBarry Smith       ilink = ilink->next;
56549bb4cd7SJungho Lee       ierr  = ISComplement(ilink->is_col,rstart,rend,&ccis);CHKERRQ(ierr);
5664aa3045dSJed Brown       ierr  = MatGetSubMatrix(pc->mat,ilink->is,ccis,MAT_INITIAL_MATRIX,&jac->C);CHKERRQ(ierr);
567fcfd50ebSBarry Smith       ierr  = ISDestroy(&ccis);CHKERRQ(ierr);
5687d50072eSJed Brown       /* Use mat[0] (diagonal block of the real matrix) preconditioned by pmat[0] */
569519d70e2SJed Brown       ierr  = MatCreateSchurComplement(jac->mat[0],jac->pmat[0],jac->B,jac->C,jac->mat[1],&jac->schur);CHKERRQ(ierr);
570bdddcaaaSMatthew G Knepley       ierr  = MatGetNullSpace(jac->pmat[1], &sp);CHKERRQ(ierr);
571bdddcaaaSMatthew G Knepley       if (sp) {ierr  = MatSetNullSpace(jac->schur, sp);CHKERRQ(ierr);}
572a04f6461SBarry Smith       /* set tabbing and options prefix of KSP inside the MatSchur */
5731cee3971SBarry Smith       ierr  = MatSchurComplementGetKSP(jac->schur,&ksp);CHKERRQ(ierr);
574e69d4d44SBarry Smith       ierr  = PetscObjectIncrementTabLevel((PetscObject)ksp,(PetscObject)pc,2);CHKERRQ(ierr);
575a04f6461SBarry Smith       ierr  = PetscSNPrintf(schurprefix,sizeof schurprefix,"%sfieldsplit_%s_",((PetscObject)pc)->prefix?((PetscObject)pc)->prefix:"",jac->head->splitname);CHKERRQ(ierr);
576a04f6461SBarry Smith       ierr  = KSPSetOptionsPrefix(ksp,schurprefix);CHKERRQ(ierr);
57720b26d62SBarry Smith       /* Need to call this everytime because new matrix is being created */
57820b26d62SBarry Smith       ierr  = MatSetFromOptions(jac->schur);CHKERRQ(ierr);
5797b62db95SJungho Lee       ierr  = MatSetUp(jac->schur);CHKERRQ(ierr);
5803b224e63SBarry Smith 
5813b224e63SBarry Smith       ierr  = KSPCreate(((PetscObject)pc)->comm,&jac->kspschur);CHKERRQ(ierr);
5829005cf84SBarry Smith       ierr  = PetscLogObjectParent((PetscObject)pc,(PetscObject)jac->kspschur);CHKERRQ(ierr);
5831cee3971SBarry Smith       ierr  = PetscObjectIncrementTabLevel((PetscObject)jac->kspschur,(PetscObject)pc,1);CHKERRQ(ierr);
584084e4875SJed Brown       ierr  = KSPSetOperators(jac->kspschur,jac->schur,FieldSplitSchurPre(jac),DIFFERENT_NONZERO_PATTERN);CHKERRQ(ierr);
585084e4875SJed Brown       if (jac->schurpre == PC_FIELDSPLIT_SCHUR_PRE_SELF) {
586084e4875SJed Brown         PC pc;
587cd5f4a64SJed Brown         ierr = KSPGetPC(jac->kspschur,&pc);CHKERRQ(ierr);
588084e4875SJed Brown         ierr = PCSetType(pc,PCNONE);CHKERRQ(ierr);
589084e4875SJed Brown         /* Note: This is bad if there exist preconditioners for MATSCHURCOMPLEMENT */
590e69d4d44SBarry Smith       }
5916c924f48SJed Brown       ierr = PetscSNPrintf(schurprefix,sizeof schurprefix,"%sfieldsplit_%s_",((PetscObject)pc)->prefix?((PetscObject)pc)->prefix:"",ilink->splitname);CHKERRQ(ierr);
5926c924f48SJed Brown       ierr  = KSPSetOptionsPrefix(jac->kspschur,schurprefix);CHKERRQ(ierr);
5933b224e63SBarry Smith       /* really want setfromoptions called in PCSetFromOptions_FieldSplit(), but it is not ready yet */
59420b26d62SBarry Smith       /* need to call this every time, since the jac->kspschur is freshly created, otherwise its options never get set */
59520b26d62SBarry Smith       ierr = KSPSetFromOptions(jac->kspschur);CHKERRQ(ierr);
5963b224e63SBarry Smith     }
597093c86ffSJed Brown 
598093c86ffSJed Brown     /* HACK: special support to forward L and Lp matrices that might be used by PCLSC */
599093c86ffSJed Brown     ierr = PetscSNPrintf(lscname,sizeof lscname,"%s_LSC_L",ilink->splitname);CHKERRQ(ierr);
600093c86ffSJed Brown     ierr = PetscObjectQuery((PetscObject)pc->mat,lscname,(PetscObject*)&LSC_L);CHKERRQ(ierr);
601093c86ffSJed Brown     if (!LSC_L) {ierr = PetscObjectQuery((PetscObject)pc->pmat,lscname,(PetscObject*)&LSC_L);CHKERRQ(ierr);}
602093c86ffSJed Brown     if (LSC_L) {ierr = PetscObjectCompose((PetscObject)jac->schur,"LSC_L",(PetscObject)LSC_L);CHKERRQ(ierr);}
603093c86ffSJed Brown     ierr = PetscSNPrintf(lscname,sizeof lscname,"%s_LSC_Lp",ilink->splitname);CHKERRQ(ierr);
604093c86ffSJed Brown     ierr = PetscObjectQuery((PetscObject)pc->pmat,lscname,(PetscObject*)&LSC_L);CHKERRQ(ierr);
605093c86ffSJed Brown     if (!LSC_L) {ierr = PetscObjectQuery((PetscObject)pc->mat,lscname,(PetscObject*)&LSC_L);CHKERRQ(ierr);}
606093c86ffSJed Brown     if (LSC_L) {ierr = PetscObjectCompose((PetscObject)jac->schur,"LSC_Lp",(PetscObject)LSC_L);CHKERRQ(ierr);}
6073b224e63SBarry Smith   } else {
60897bbdb24SBarry Smith     /* set up the individual PCs */
60997bbdb24SBarry Smith     i    = 0;
6105a9f2f41SSatish Balay     ilink = jac->head;
6115a9f2f41SSatish Balay     while (ilink) {
612519d70e2SJed Brown       ierr = KSPSetOperators(ilink->ksp,jac->mat[i],jac->pmat[i],flag);CHKERRQ(ierr);
6133b224e63SBarry Smith       /* really want setfromoptions called in PCSetFromOptions_FieldSplit(), but it is not ready yet */
614c1570756SJed Brown       if (!jac->suboptionsset) {ierr = KSPSetFromOptions(ilink->ksp);CHKERRQ(ierr);}
6155a9f2f41SSatish Balay       ierr = KSPSetUp(ilink->ksp);CHKERRQ(ierr);
61697bbdb24SBarry Smith       i++;
6175a9f2f41SSatish Balay       ilink = ilink->next;
6180971522cSBarry Smith     }
6193b224e63SBarry Smith   }
6203b224e63SBarry Smith 
621c1570756SJed Brown   jac->suboptionsset = PETSC_TRUE;
6220971522cSBarry Smith   PetscFunctionReturn(0);
6230971522cSBarry Smith }
6240971522cSBarry Smith 
6255a9f2f41SSatish Balay #define FieldSplitSplitSolveAdd(ilink,xx,yy) \
626ca9f406cSSatish Balay     (VecScatterBegin(ilink->sctx,xx,ilink->x,INSERT_VALUES,SCATTER_FORWARD) || \
627ca9f406cSSatish Balay      VecScatterEnd(ilink->sctx,xx,ilink->x,INSERT_VALUES,SCATTER_FORWARD) || \
6285a9f2f41SSatish Balay      KSPSolve(ilink->ksp,ilink->x,ilink->y) || \
629ca9f406cSSatish Balay      VecScatterBegin(ilink->sctx,ilink->y,yy,ADD_VALUES,SCATTER_REVERSE) || \
630ca9f406cSSatish Balay      VecScatterEnd(ilink->sctx,ilink->y,yy,ADD_VALUES,SCATTER_REVERSE))
63179416396SBarry Smith 
6320971522cSBarry Smith #undef __FUNCT__
6333b224e63SBarry Smith #define __FUNCT__ "PCApply_FieldSplit_Schur"
6343b224e63SBarry Smith static PetscErrorCode PCApply_FieldSplit_Schur(PC pc,Vec x,Vec y)
6353b224e63SBarry Smith {
6363b224e63SBarry Smith   PC_FieldSplit     *jac = (PC_FieldSplit*)pc->data;
6373b224e63SBarry Smith   PetscErrorCode    ierr;
6383b224e63SBarry Smith   KSP               ksp;
6393b224e63SBarry Smith   PC_FieldSplitLink ilinkA = jac->head, ilinkD = ilinkA->next;
6403b224e63SBarry Smith 
6413b224e63SBarry Smith   PetscFunctionBegin;
6423b224e63SBarry Smith   ierr = MatSchurComplementGetKSP(jac->schur,&ksp);CHKERRQ(ierr);
6433b224e63SBarry Smith 
644c5d2311dSJed Brown   switch (jac->schurfactorization) {
645c9c6ffaaSJed Brown     case PC_FIELDSPLIT_SCHUR_FACT_DIAG:
646a04f6461SBarry Smith       /* [A00 0; 0 -S], positive definite, suitable for MINRES */
647c5d2311dSJed Brown       ierr = VecScatterBegin(ilinkA->sctx,x,ilinkA->x,INSERT_VALUES,SCATTER_FORWARD);CHKERRQ(ierr);
648c5d2311dSJed Brown       ierr = VecScatterBegin(ilinkD->sctx,x,ilinkD->x,INSERT_VALUES,SCATTER_FORWARD);CHKERRQ(ierr);
649c5d2311dSJed Brown       ierr = VecScatterEnd(ilinkA->sctx,x,ilinkA->x,INSERT_VALUES,SCATTER_FORWARD);CHKERRQ(ierr);
650c5d2311dSJed Brown       ierr = KSPSolve(ksp,ilinkA->x,ilinkA->y);CHKERRQ(ierr);
651c5d2311dSJed Brown       ierr = VecScatterBegin(ilinkA->sctx,ilinkA->y,y,INSERT_VALUES,SCATTER_REVERSE);CHKERRQ(ierr);
652c5d2311dSJed Brown       ierr = VecScatterEnd(ilinkD->sctx,x,ilinkD->x,INSERT_VALUES,SCATTER_FORWARD);CHKERRQ(ierr);
653c5d2311dSJed Brown       ierr = KSPSolve(jac->kspschur,ilinkD->x,ilinkD->y);CHKERRQ(ierr);
654c5d2311dSJed Brown       ierr = VecScale(ilinkD->y,-1.);CHKERRQ(ierr);
655c5d2311dSJed Brown       ierr = VecScatterBegin(ilinkD->sctx,ilinkD->y,y,INSERT_VALUES,SCATTER_REVERSE);CHKERRQ(ierr);
656c5d2311dSJed Brown       ierr = VecScatterEnd(ilinkA->sctx,ilinkA->y,y,INSERT_VALUES,SCATTER_REVERSE);CHKERRQ(ierr);
657c5d2311dSJed Brown       ierr = VecScatterEnd(ilinkD->sctx,ilinkD->y,y,INSERT_VALUES,SCATTER_REVERSE);CHKERRQ(ierr);
658c5d2311dSJed Brown       break;
659c9c6ffaaSJed Brown     case PC_FIELDSPLIT_SCHUR_FACT_LOWER:
660a04f6461SBarry Smith       /* [A00 0; A10 S], suitable for left preconditioning */
661c5d2311dSJed Brown       ierr = VecScatterBegin(ilinkA->sctx,x,ilinkA->x,INSERT_VALUES,SCATTER_FORWARD);CHKERRQ(ierr);
662c5d2311dSJed Brown       ierr = VecScatterEnd(ilinkA->sctx,x,ilinkA->x,INSERT_VALUES,SCATTER_FORWARD);CHKERRQ(ierr);
663c5d2311dSJed Brown       ierr = KSPSolve(ksp,ilinkA->x,ilinkA->y);CHKERRQ(ierr);
664c5d2311dSJed Brown       ierr = MatMult(jac->C,ilinkA->y,ilinkD->x);CHKERRQ(ierr);
665c5d2311dSJed Brown       ierr = VecScale(ilinkD->x,-1.);CHKERRQ(ierr);
666c5d2311dSJed Brown       ierr = VecScatterBegin(ilinkD->sctx,x,ilinkD->x,ADD_VALUES,SCATTER_FORWARD);CHKERRQ(ierr);
667c5d2311dSJed Brown       ierr = VecScatterBegin(ilinkA->sctx,ilinkA->y,y,INSERT_VALUES,SCATTER_REVERSE);CHKERRQ(ierr);
668c5d2311dSJed Brown       ierr = VecScatterEnd(ilinkD->sctx,x,ilinkD->x,ADD_VALUES,SCATTER_FORWARD);CHKERRQ(ierr);
669c5d2311dSJed Brown       ierr = KSPSolve(jac->kspschur,ilinkD->x,ilinkD->y);CHKERRQ(ierr);
670c5d2311dSJed Brown       ierr = VecScatterBegin(ilinkD->sctx,ilinkD->y,y,INSERT_VALUES,SCATTER_REVERSE);CHKERRQ(ierr);
671c5d2311dSJed Brown       ierr = VecScatterEnd(ilinkA->sctx,ilinkA->y,y,INSERT_VALUES,SCATTER_REVERSE);CHKERRQ(ierr);
672c5d2311dSJed Brown       ierr = VecScatterEnd(ilinkD->sctx,ilinkD->y,y,INSERT_VALUES,SCATTER_REVERSE);CHKERRQ(ierr);
673c5d2311dSJed Brown       break;
674c9c6ffaaSJed Brown     case PC_FIELDSPLIT_SCHUR_FACT_UPPER:
675a04f6461SBarry Smith       /* [A00 A01; 0 S], suitable for right preconditioning */
676c5d2311dSJed Brown       ierr = VecScatterBegin(ilinkD->sctx,x,ilinkD->x,INSERT_VALUES,SCATTER_FORWARD);CHKERRQ(ierr);
677c5d2311dSJed Brown       ierr = VecScatterEnd(ilinkD->sctx,x,ilinkD->x,INSERT_VALUES,SCATTER_FORWARD);CHKERRQ(ierr);
678c5d2311dSJed Brown       ierr = KSPSolve(jac->kspschur,ilinkD->x,ilinkD->y);CHKERRQ(ierr);
679c5d2311dSJed Brown       ierr = MatMult(jac->B,ilinkD->y,ilinkA->x);CHKERRQ(ierr);
680c5d2311dSJed Brown       ierr = VecScale(ilinkA->x,-1.);CHKERRQ(ierr);
681c5d2311dSJed Brown       ierr = VecScatterBegin(ilinkA->sctx,x,ilinkA->x,ADD_VALUES,SCATTER_FORWARD);CHKERRQ(ierr);
682c5d2311dSJed Brown       ierr = VecScatterBegin(ilinkD->sctx,ilinkD->y,y,INSERT_VALUES,SCATTER_REVERSE);CHKERRQ(ierr);
683c5d2311dSJed Brown       ierr = VecScatterEnd(ilinkA->sctx,x,ilinkA->x,ADD_VALUES,SCATTER_FORWARD);CHKERRQ(ierr);
684c5d2311dSJed Brown       ierr = KSPSolve(ksp,ilinkA->x,ilinkA->y);CHKERRQ(ierr);
685c5d2311dSJed Brown       ierr = VecScatterBegin(ilinkA->sctx,ilinkA->y,y,INSERT_VALUES,SCATTER_REVERSE);CHKERRQ(ierr);
686c5d2311dSJed Brown       ierr = VecScatterEnd(ilinkD->sctx,ilinkD->y,y,INSERT_VALUES,SCATTER_REVERSE);CHKERRQ(ierr);
687c5d2311dSJed Brown       ierr = VecScatterEnd(ilinkA->sctx,ilinkA->y,y,INSERT_VALUES,SCATTER_REVERSE);CHKERRQ(ierr);
688c5d2311dSJed Brown       break;
689c9c6ffaaSJed Brown     case PC_FIELDSPLIT_SCHUR_FACT_FULL:
690a04f6461SBarry Smith       /* [1 0; A10 A00^{-1} 1] [A00 0; 0 S] [1 A00^{-1}A01; 0 1], an exact solve if applied exactly, needs one extra solve with A */
6913b224e63SBarry Smith       ierr = VecScatterBegin(ilinkA->sctx,x,ilinkA->x,INSERT_VALUES,SCATTER_FORWARD);CHKERRQ(ierr);
6923b224e63SBarry Smith       ierr = VecScatterEnd(ilinkA->sctx,x,ilinkA->x,INSERT_VALUES,SCATTER_FORWARD);CHKERRQ(ierr);
6933b224e63SBarry Smith       ierr = KSPSolve(ksp,ilinkA->x,ilinkA->y);CHKERRQ(ierr);
6943b224e63SBarry Smith       ierr = MatMult(jac->C,ilinkA->y,ilinkD->x);CHKERRQ(ierr);
6953b224e63SBarry Smith       ierr = VecScale(ilinkD->x,-1.0);CHKERRQ(ierr);
6963b224e63SBarry Smith       ierr = VecScatterBegin(ilinkD->sctx,x,ilinkD->x,ADD_VALUES,SCATTER_FORWARD);CHKERRQ(ierr);
6973b224e63SBarry Smith       ierr = VecScatterEnd(ilinkD->sctx,x,ilinkD->x,ADD_VALUES,SCATTER_FORWARD);CHKERRQ(ierr);
6983b224e63SBarry Smith 
6993b224e63SBarry Smith       ierr = KSPSolve(jac->kspschur,ilinkD->x,ilinkD->y);CHKERRQ(ierr);
7003b224e63SBarry Smith       ierr = VecScatterBegin(ilinkD->sctx,ilinkD->y,y,INSERT_VALUES,SCATTER_REVERSE);CHKERRQ(ierr);
7013b224e63SBarry Smith       ierr = VecScatterEnd(ilinkD->sctx,ilinkD->y,y,INSERT_VALUES,SCATTER_REVERSE);CHKERRQ(ierr);
7023b224e63SBarry Smith 
7033b224e63SBarry Smith       ierr = MatMult(jac->B,ilinkD->y,ilinkA->y);CHKERRQ(ierr);
7043b224e63SBarry Smith       ierr = VecAXPY(ilinkA->x,-1.0,ilinkA->y);CHKERRQ(ierr);
7053b224e63SBarry Smith       ierr = KSPSolve(ksp,ilinkA->x,ilinkA->y);CHKERRQ(ierr);
7063b224e63SBarry Smith       ierr = VecScatterBegin(ilinkA->sctx,ilinkA->y,y,INSERT_VALUES,SCATTER_REVERSE);CHKERRQ(ierr);
7073b224e63SBarry Smith       ierr = VecScatterEnd(ilinkA->sctx,ilinkA->y,y,INSERT_VALUES,SCATTER_REVERSE);CHKERRQ(ierr);
708c5d2311dSJed Brown   }
7093b224e63SBarry Smith   PetscFunctionReturn(0);
7103b224e63SBarry Smith }
7113b224e63SBarry Smith 
7123b224e63SBarry Smith #undef __FUNCT__
7130971522cSBarry Smith #define __FUNCT__ "PCApply_FieldSplit"
7140971522cSBarry Smith static PetscErrorCode PCApply_FieldSplit(PC pc,Vec x,Vec y)
7150971522cSBarry Smith {
7160971522cSBarry Smith   PC_FieldSplit     *jac = (PC_FieldSplit*)pc->data;
7170971522cSBarry Smith   PetscErrorCode    ierr;
7185a9f2f41SSatish Balay   PC_FieldSplitLink ilink = jac->head;
719939b8a20SBarry Smith   PetscInt          cnt,bs;
7200971522cSBarry Smith 
7210971522cSBarry Smith   PetscFunctionBegin;
72251f519a2SBarry Smith   CHKMEMQ;
72379416396SBarry Smith   if (jac->type == PC_COMPOSITE_ADDITIVE) {
7241b9fc7fcSBarry Smith     if (jac->defaultsplit) {
725939b8a20SBarry Smith       ierr = VecGetBlockSize(x,&bs);CHKERRQ(ierr);
726939b8a20SBarry Smith       if (jac->bs > 0 && bs != jac->bs) SETERRQ2(((PetscObject)pc)->comm,PETSC_ERR_ARG_WRONGSTATE,"Blocksize of x vector %D does not match fieldsplit blocksize %D",bs,jac->bs);
727939b8a20SBarry Smith       ierr = VecGetBlockSize(y,&bs);CHKERRQ(ierr);
728939b8a20SBarry Smith       if (jac->bs > 0 && bs != jac->bs) SETERRQ2(((PetscObject)pc)->comm,PETSC_ERR_ARG_WRONGSTATE,"Blocksize of y vector %D does not match fieldsplit blocksize %D",bs,jac->bs);
7290971522cSBarry Smith       ierr = VecStrideGatherAll(x,jac->x,INSERT_VALUES);CHKERRQ(ierr);
7305a9f2f41SSatish Balay       while (ilink) {
7315a9f2f41SSatish Balay         ierr = KSPSolve(ilink->ksp,ilink->x,ilink->y);CHKERRQ(ierr);
7325a9f2f41SSatish Balay         ilink = ilink->next;
7330971522cSBarry Smith       }
7340971522cSBarry Smith       ierr = VecStrideScatterAll(jac->y,y,INSERT_VALUES);CHKERRQ(ierr);
7351b9fc7fcSBarry Smith     } else {
736efb30889SBarry Smith       ierr = VecSet(y,0.0);CHKERRQ(ierr);
7375a9f2f41SSatish Balay       while (ilink) {
7385a9f2f41SSatish Balay         ierr = FieldSplitSplitSolveAdd(ilink,x,y);CHKERRQ(ierr);
7395a9f2f41SSatish Balay         ilink = ilink->next;
7401b9fc7fcSBarry Smith       }
7411b9fc7fcSBarry Smith     }
74216913363SBarry Smith   } else if (jac->type == PC_COMPOSITE_MULTIPLICATIVE || jac->type == PC_COMPOSITE_SYMMETRIC_MULTIPLICATIVE) {
74379416396SBarry Smith     if (!jac->w1) {
74479416396SBarry Smith       ierr = VecDuplicate(x,&jac->w1);CHKERRQ(ierr);
74579416396SBarry Smith       ierr = VecDuplicate(x,&jac->w2);CHKERRQ(ierr);
74679416396SBarry Smith     }
747efb30889SBarry Smith     ierr = VecSet(y,0.0);CHKERRQ(ierr);
7485a9f2f41SSatish Balay     ierr = FieldSplitSplitSolveAdd(ilink,x,y);CHKERRQ(ierr);
7493e197d65SBarry Smith     cnt = 1;
7505a9f2f41SSatish Balay     while (ilink->next) {
7515a9f2f41SSatish Balay       ilink = ilink->next;
7523e197d65SBarry Smith       /* compute the residual only over the part of the vector needed */
7533e197d65SBarry Smith       ierr = MatMult(jac->Afield[cnt++],y,ilink->x);CHKERRQ(ierr);
7543e197d65SBarry Smith       ierr = VecScale(ilink->x,-1.0);CHKERRQ(ierr);
7553e197d65SBarry Smith       ierr = VecScatterBegin(ilink->sctx,x,ilink->x,ADD_VALUES,SCATTER_FORWARD);CHKERRQ(ierr);
7563e197d65SBarry Smith       ierr = VecScatterEnd(ilink->sctx,x,ilink->x,ADD_VALUES,SCATTER_FORWARD);CHKERRQ(ierr);
7573e197d65SBarry Smith       ierr = KSPSolve(ilink->ksp,ilink->x,ilink->y);CHKERRQ(ierr);
7583e197d65SBarry Smith       ierr = VecScatterBegin(ilink->sctx,ilink->y,y,ADD_VALUES,SCATTER_REVERSE);CHKERRQ(ierr);
7593e197d65SBarry Smith       ierr = VecScatterEnd(ilink->sctx,ilink->y,y,ADD_VALUES,SCATTER_REVERSE);CHKERRQ(ierr);
7603e197d65SBarry Smith     }
76151f519a2SBarry Smith     if (jac->type == PC_COMPOSITE_SYMMETRIC_MULTIPLICATIVE) {
76211755939SBarry Smith       cnt -= 2;
76351f519a2SBarry Smith       while (ilink->previous) {
76451f519a2SBarry Smith         ilink = ilink->previous;
76511755939SBarry Smith         /* compute the residual only over the part of the vector needed */
76611755939SBarry Smith         ierr = MatMult(jac->Afield[cnt--],y,ilink->x);CHKERRQ(ierr);
76711755939SBarry Smith         ierr = VecScale(ilink->x,-1.0);CHKERRQ(ierr);
76811755939SBarry Smith         ierr = VecScatterBegin(ilink->sctx,x,ilink->x,ADD_VALUES,SCATTER_FORWARD);CHKERRQ(ierr);
76911755939SBarry Smith         ierr = VecScatterEnd(ilink->sctx,x,ilink->x,ADD_VALUES,SCATTER_FORWARD);CHKERRQ(ierr);
77011755939SBarry Smith         ierr = KSPSolve(ilink->ksp,ilink->x,ilink->y);CHKERRQ(ierr);
77111755939SBarry Smith         ierr = VecScatterBegin(ilink->sctx,ilink->y,y,ADD_VALUES,SCATTER_REVERSE);CHKERRQ(ierr);
77211755939SBarry Smith         ierr = VecScatterEnd(ilink->sctx,ilink->y,y,ADD_VALUES,SCATTER_REVERSE);CHKERRQ(ierr);
77351f519a2SBarry Smith       }
77411755939SBarry Smith     }
77565e19b50SBarry Smith   } else SETERRQ1(((PetscObject)pc)->comm,PETSC_ERR_SUP,"Unsupported or unknown composition",(int) jac->type);
77651f519a2SBarry Smith   CHKMEMQ;
7770971522cSBarry Smith   PetscFunctionReturn(0);
7780971522cSBarry Smith }
7790971522cSBarry Smith 
780421e10b8SBarry Smith #define FieldSplitSplitSolveAddTranspose(ilink,xx,yy) \
781ca9f406cSSatish Balay     (VecScatterBegin(ilink->sctx,xx,ilink->y,INSERT_VALUES,SCATTER_FORWARD) || \
782ca9f406cSSatish Balay      VecScatterEnd(ilink->sctx,xx,ilink->y,INSERT_VALUES,SCATTER_FORWARD) || \
783421e10b8SBarry Smith      KSPSolveTranspose(ilink->ksp,ilink->y,ilink->x) || \
784ca9f406cSSatish Balay      VecScatterBegin(ilink->sctx,ilink->x,yy,ADD_VALUES,SCATTER_REVERSE) || \
785ca9f406cSSatish Balay      VecScatterEnd(ilink->sctx,ilink->x,yy,ADD_VALUES,SCATTER_REVERSE))
786421e10b8SBarry Smith 
787421e10b8SBarry Smith #undef __FUNCT__
7888c03b21aSDmitry Karpeev #define __FUNCT__ "PCApplyTranspose_FieldSplit"
789421e10b8SBarry Smith static PetscErrorCode PCApplyTranspose_FieldSplit(PC pc,Vec x,Vec y)
790421e10b8SBarry Smith {
791421e10b8SBarry Smith   PC_FieldSplit     *jac = (PC_FieldSplit*)pc->data;
792421e10b8SBarry Smith   PetscErrorCode    ierr;
793421e10b8SBarry Smith   PC_FieldSplitLink ilink = jac->head;
794939b8a20SBarry Smith   PetscInt          bs;
795421e10b8SBarry Smith 
796421e10b8SBarry Smith   PetscFunctionBegin;
797421e10b8SBarry Smith   CHKMEMQ;
798421e10b8SBarry Smith   if (jac->type == PC_COMPOSITE_ADDITIVE) {
799421e10b8SBarry Smith     if (jac->defaultsplit) {
800939b8a20SBarry Smith       ierr = VecGetBlockSize(x,&bs);CHKERRQ(ierr);
801939b8a20SBarry Smith       if (jac->bs > 0 && bs != jac->bs) SETERRQ2(((PetscObject)pc)->comm,PETSC_ERR_ARG_WRONGSTATE,"Blocksize of x vector %D does not match fieldsplit blocksize %D",bs,jac->bs);
802939b8a20SBarry Smith       ierr = VecGetBlockSize(y,&bs);CHKERRQ(ierr);
803939b8a20SBarry Smith       if (jac->bs > 0 && bs != jac->bs) SETERRQ2(((PetscObject)pc)->comm,PETSC_ERR_ARG_WRONGSTATE,"Blocksize of y vector %D does not match fieldsplit blocksize %D",bs,jac->bs);
804421e10b8SBarry Smith       ierr = VecStrideGatherAll(x,jac->x,INSERT_VALUES);CHKERRQ(ierr);
805421e10b8SBarry Smith       while (ilink) {
806421e10b8SBarry Smith 	ierr = KSPSolveTranspose(ilink->ksp,ilink->x,ilink->y);CHKERRQ(ierr);
807421e10b8SBarry Smith 	ilink = ilink->next;
808421e10b8SBarry Smith       }
809421e10b8SBarry Smith       ierr = VecStrideScatterAll(jac->y,y,INSERT_VALUES);CHKERRQ(ierr);
810421e10b8SBarry Smith     } else {
811421e10b8SBarry Smith       ierr = VecSet(y,0.0);CHKERRQ(ierr);
812421e10b8SBarry Smith       while (ilink) {
813421e10b8SBarry Smith         ierr = FieldSplitSplitSolveAddTranspose(ilink,x,y);CHKERRQ(ierr);
814421e10b8SBarry Smith 	ilink = ilink->next;
815421e10b8SBarry Smith       }
816421e10b8SBarry Smith     }
817421e10b8SBarry Smith   } else {
818421e10b8SBarry Smith     if (!jac->w1) {
819421e10b8SBarry Smith       ierr = VecDuplicate(x,&jac->w1);CHKERRQ(ierr);
820421e10b8SBarry Smith       ierr = VecDuplicate(x,&jac->w2);CHKERRQ(ierr);
821421e10b8SBarry Smith     }
822421e10b8SBarry Smith     ierr = VecSet(y,0.0);CHKERRQ(ierr);
823421e10b8SBarry Smith     if (jac->type == PC_COMPOSITE_SYMMETRIC_MULTIPLICATIVE) {
824421e10b8SBarry Smith       ierr = FieldSplitSplitSolveAddTranspose(ilink,x,y);CHKERRQ(ierr);
825421e10b8SBarry Smith       while (ilink->next) {
826421e10b8SBarry Smith         ilink = ilink->next;
8279989ab13SBarry Smith         ierr  = MatMultTranspose(pc->mat,y,jac->w1);CHKERRQ(ierr);
828421e10b8SBarry Smith         ierr  = VecWAXPY(jac->w2,-1.0,jac->w1,x);CHKERRQ(ierr);
829421e10b8SBarry Smith         ierr  = FieldSplitSplitSolveAddTranspose(ilink,jac->w2,y);CHKERRQ(ierr);
830421e10b8SBarry Smith       }
831421e10b8SBarry Smith       while (ilink->previous) {
832421e10b8SBarry Smith         ilink = ilink->previous;
8339989ab13SBarry Smith         ierr  = MatMultTranspose(pc->mat,y,jac->w1);CHKERRQ(ierr);
834421e10b8SBarry Smith         ierr  = VecWAXPY(jac->w2,-1.0,jac->w1,x);CHKERRQ(ierr);
835421e10b8SBarry Smith         ierr  = FieldSplitSplitSolveAddTranspose(ilink,jac->w2,y);CHKERRQ(ierr);
836421e10b8SBarry Smith       }
837421e10b8SBarry Smith     } else {
838421e10b8SBarry Smith       while (ilink->next) {   /* get to last entry in linked list */
839421e10b8SBarry Smith 	ilink = ilink->next;
840421e10b8SBarry Smith       }
841421e10b8SBarry Smith       ierr = FieldSplitSplitSolveAddTranspose(ilink,x,y);CHKERRQ(ierr);
842421e10b8SBarry Smith       while (ilink->previous) {
843421e10b8SBarry Smith 	ilink = ilink->previous;
8449989ab13SBarry Smith 	ierr  = MatMultTranspose(pc->mat,y,jac->w1);CHKERRQ(ierr);
845421e10b8SBarry Smith 	ierr  = VecWAXPY(jac->w2,-1.0,jac->w1,x);CHKERRQ(ierr);
846421e10b8SBarry Smith 	ierr  = FieldSplitSplitSolveAddTranspose(ilink,jac->w2,y);CHKERRQ(ierr);
847421e10b8SBarry Smith       }
848421e10b8SBarry Smith     }
849421e10b8SBarry Smith   }
850421e10b8SBarry Smith   CHKMEMQ;
851421e10b8SBarry Smith   PetscFunctionReturn(0);
852421e10b8SBarry Smith }
853421e10b8SBarry Smith 
8540971522cSBarry Smith #undef __FUNCT__
855574deadeSBarry Smith #define __FUNCT__ "PCReset_FieldSplit"
856574deadeSBarry Smith static PetscErrorCode PCReset_FieldSplit(PC pc)
8570971522cSBarry Smith {
8580971522cSBarry Smith   PC_FieldSplit     *jac = (PC_FieldSplit*)pc->data;
8590971522cSBarry Smith   PetscErrorCode    ierr;
8605a9f2f41SSatish Balay   PC_FieldSplitLink ilink = jac->head,next;
8610971522cSBarry Smith 
8620971522cSBarry Smith   PetscFunctionBegin;
8635a9f2f41SSatish Balay   while (ilink) {
864574deadeSBarry Smith     ierr = KSPReset(ilink->ksp);CHKERRQ(ierr);
865fcfd50ebSBarry Smith     ierr = VecDestroy(&ilink->x);CHKERRQ(ierr);
866fcfd50ebSBarry Smith     ierr = VecDestroy(&ilink->y);CHKERRQ(ierr);
867fcfd50ebSBarry Smith     ierr = VecScatterDestroy(&ilink->sctx);CHKERRQ(ierr);
868fcfd50ebSBarry Smith     ierr = ISDestroy(&ilink->is);CHKERRQ(ierr);
869b5787286SJed Brown     ierr = ISDestroy(&ilink->is_col);CHKERRQ(ierr);
8705a9f2f41SSatish Balay     next = ilink->next;
8715a9f2f41SSatish Balay     ilink = next;
8720971522cSBarry Smith   }
87305b42c5fSBarry Smith   ierr = PetscFree2(jac->x,jac->y);CHKERRQ(ierr);
874574deadeSBarry Smith   if (jac->mat && jac->mat != jac->pmat) {
875574deadeSBarry Smith     ierr = MatDestroyMatrices(jac->nsplits,&jac->mat);CHKERRQ(ierr);
876574deadeSBarry Smith   } else if (jac->mat) {
877574deadeSBarry Smith     jac->mat = PETSC_NULL;
878574deadeSBarry Smith   }
87997bbdb24SBarry Smith   if (jac->pmat) {ierr = MatDestroyMatrices(jac->nsplits,&jac->pmat);CHKERRQ(ierr);}
88068dd23aaSBarry Smith   if (jac->Afield) {ierr = MatDestroyMatrices(jac->nsplits,&jac->Afield);CHKERRQ(ierr);}
8816bf464f9SBarry Smith   ierr = VecDestroy(&jac->w1);CHKERRQ(ierr);
8826bf464f9SBarry Smith   ierr = VecDestroy(&jac->w2);CHKERRQ(ierr);
8836bf464f9SBarry Smith   ierr = MatDestroy(&jac->schur);CHKERRQ(ierr);
8846bf464f9SBarry Smith   ierr = MatDestroy(&jac->schur_user);CHKERRQ(ierr);
8856bf464f9SBarry Smith   ierr = KSPDestroy(&jac->kspschur);CHKERRQ(ierr);
8866bf464f9SBarry Smith   ierr = MatDestroy(&jac->B);CHKERRQ(ierr);
8876bf464f9SBarry Smith   ierr = MatDestroy(&jac->C);CHKERRQ(ierr);
88863ec74ffSBarry Smith   jac->reset = PETSC_TRUE;
889574deadeSBarry Smith   PetscFunctionReturn(0);
890574deadeSBarry Smith }
891574deadeSBarry Smith 
892574deadeSBarry Smith #undef __FUNCT__
893574deadeSBarry Smith #define __FUNCT__ "PCDestroy_FieldSplit"
894574deadeSBarry Smith static PetscErrorCode PCDestroy_FieldSplit(PC pc)
895574deadeSBarry Smith {
896574deadeSBarry Smith   PC_FieldSplit     *jac = (PC_FieldSplit*)pc->data;
897574deadeSBarry Smith   PetscErrorCode    ierr;
898574deadeSBarry Smith   PC_FieldSplitLink ilink = jac->head,next;
899574deadeSBarry Smith 
900574deadeSBarry Smith   PetscFunctionBegin;
901574deadeSBarry Smith   ierr = PCReset_FieldSplit(pc);CHKERRQ(ierr);
902574deadeSBarry Smith   while (ilink) {
9036bf464f9SBarry Smith     ierr = KSPDestroy(&ilink->ksp);CHKERRQ(ierr);
904574deadeSBarry Smith     next = ilink->next;
905574deadeSBarry Smith     ierr = PetscFree(ilink->splitname);CHKERRQ(ierr);
906574deadeSBarry Smith     ierr = PetscFree(ilink->fields);CHKERRQ(ierr);
9075d4c12cdSJungho Lee     ierr = PetscFree(ilink->fields_col);CHKERRQ(ierr);
908574deadeSBarry Smith     ierr = PetscFree(ilink);CHKERRQ(ierr);
909574deadeSBarry Smith     ilink = next;
910574deadeSBarry Smith   }
911574deadeSBarry Smith   ierr = PetscFree2(jac->x,jac->y);CHKERRQ(ierr);
912c31cb41cSBarry Smith   ierr = PetscFree(pc->data);CHKERRQ(ierr);
9137b62db95SJungho Lee   ierr = PetscObjectComposeFunctionDynamic((PetscObject)pc,"PCFieldSplitGetSubKSP_C","",PETSC_NULL);CHKERRQ(ierr);
9147b62db95SJungho Lee   ierr = PetscObjectComposeFunctionDynamic((PetscObject)pc,"PCFieldSplitSetFields_C","",PETSC_NULL);CHKERRQ(ierr);
9157b62db95SJungho Lee   ierr = PetscObjectComposeFunctionDynamic((PetscObject)pc,"PCFieldSplitSetIS_C","",PETSC_NULL);CHKERRQ(ierr);
9167b62db95SJungho Lee   ierr = PetscObjectComposeFunctionDynamic((PetscObject)pc,"PCFieldSplitSetType_C","",PETSC_NULL);CHKERRQ(ierr);
9177b62db95SJungho Lee   ierr = PetscObjectComposeFunctionDynamic((PetscObject)pc,"PCFieldSplitSetBlockSize_C","",PETSC_NULL);CHKERRQ(ierr);
918ab1df9f5SJed Brown   ierr = PetscObjectComposeFunctionDynamic((PetscObject)pc,"PCFieldSplitSchurPrecondition_C","",PETSC_NULL);CHKERRQ(ierr);
919c9c6ffaaSJed Brown   ierr = PetscObjectComposeFunctionDynamic((PetscObject)pc,"PCFieldSplitSetSchurFactType_C","",PETSC_NULL);CHKERRQ(ierr);
9200971522cSBarry Smith   PetscFunctionReturn(0);
9210971522cSBarry Smith }
9220971522cSBarry Smith 
9230971522cSBarry Smith #undef __FUNCT__
9240971522cSBarry Smith #define __FUNCT__ "PCSetFromOptions_FieldSplit"
9250971522cSBarry Smith static PetscErrorCode PCSetFromOptions_FieldSplit(PC pc)
9260971522cSBarry Smith {
9271b9fc7fcSBarry Smith   PetscErrorCode  ierr;
9286c924f48SJed Brown   PetscInt        bs;
929bc59fbc5SBarry Smith   PetscBool       flg,stokes = PETSC_FALSE;
9309dcbbd2bSBarry Smith   PC_FieldSplit   *jac = (PC_FieldSplit*)pc->data;
9313b224e63SBarry Smith   PCCompositeType ctype;
932e7c4fc90SDmitry Karpeev   DM              ddm;
933e7c4fc90SDmitry Karpeev   char            ddm_name[1025];
9341b9fc7fcSBarry Smith 
9350971522cSBarry Smith   PetscFunctionBegin;
9361b9fc7fcSBarry Smith   ierr = PetscOptionsHead("FieldSplit options");CHKERRQ(ierr);
937e7c4fc90SDmitry Karpeev   if(pc->dm) {
938e7c4fc90SDmitry Karpeev     /* Allow the user to request a decomposition DM by name */
939e7c4fc90SDmitry Karpeev     ierr = PetscStrncpy(ddm_name, "", 1024); CHKERRQ(ierr);
940e7c4fc90SDmitry Karpeev     ierr = PetscOptionsString("-pc_fieldsplit_decomposition_dm", "Name of the DM defining the composition", "PCSetDM", ddm_name, ddm_name,1024,&flg); CHKERRQ(ierr);
941e7c4fc90SDmitry Karpeev     if(flg) {
942e7c4fc90SDmitry Karpeev       ierr = DMCreateDecompositionDM(pc->dm, ddm_name, &ddm); CHKERRQ(ierr);
943e7c4fc90SDmitry Karpeev       if(!ddm) {
944e7c4fc90SDmitry Karpeev         SETERRQ1(((PetscObject)pc)->comm, PETSC_ERR_ARG_WRONGSTATE, "Uknown DM decomposition name %s", ddm_name);
945e7c4fc90SDmitry Karpeev       }
946e7c4fc90SDmitry Karpeev       ierr = PetscInfo(pc,"Using decomposition DM defined using options database\n");CHKERRQ(ierr);
947e7c4fc90SDmitry Karpeev       ierr = PCSetDM(pc,ddm); CHKERRQ(ierr);
948e7c4fc90SDmitry Karpeev     }
949e7c4fc90SDmitry Karpeev   }
950acfcf0e5SJed Brown   ierr = PetscOptionsBool("-pc_fieldsplit_real_diagonal","Use diagonal blocks of the operator","PCFieldSplitSetRealDiagonal",jac->realdiagonal,&jac->realdiagonal,PETSC_NULL);CHKERRQ(ierr);
95151f519a2SBarry Smith   ierr = PetscOptionsInt("-pc_fieldsplit_block_size","Blocksize that defines number of fields","PCFieldSplitSetBlockSize",jac->bs,&bs,&flg);CHKERRQ(ierr);
95251f519a2SBarry Smith   if (flg) {
95351f519a2SBarry Smith     ierr = PCFieldSplitSetBlockSize(pc,bs);CHKERRQ(ierr);
95451f519a2SBarry Smith   }
955704ba839SBarry Smith 
956435f959eSBarry Smith   ierr = PetscOptionsGetBool(((PetscObject)pc)->prefix,"-pc_fieldsplit_detect_saddle_point",&stokes,PETSC_NULL);CHKERRQ(ierr);
957c0adfefeSBarry Smith   if (stokes) {
958c0adfefeSBarry Smith     ierr = PCFieldSplitSetType(pc,PC_COMPOSITE_SCHUR);CHKERRQ(ierr);
959c0adfefeSBarry Smith     jac->schurpre = PC_FIELDSPLIT_SCHUR_PRE_SELF;
960c0adfefeSBarry Smith   }
961c0adfefeSBarry Smith 
9623b224e63SBarry Smith   ierr = PetscOptionsEnum("-pc_fieldsplit_type","Type of composition","PCFieldSplitSetType",PCCompositeTypes,(PetscEnum)jac->type,(PetscEnum*)&ctype,&flg);CHKERRQ(ierr);
9633b224e63SBarry Smith   if (flg) {
9643b224e63SBarry Smith     ierr = PCFieldSplitSetType(pc,ctype);CHKERRQ(ierr);
9653b224e63SBarry Smith   }
966c30613efSMatthew Knepley   /* Only setup fields once */
967c30613efSMatthew Knepley   if ((jac->bs > 0) && (jac->nsplits == 0)) {
968d32f9abdSBarry Smith     /* only allow user to set fields from command line if bs is already known.
969d32f9abdSBarry Smith        otherwise user can set them in PCFieldSplitSetDefaults() */
9706c924f48SJed Brown     ierr = PCFieldSplitSetRuntimeSplits_Private(pc);CHKERRQ(ierr);
9716c924f48SJed Brown     if (jac->splitdefined) {ierr = PetscInfo(pc,"Splits defined using the options database\n");CHKERRQ(ierr);}
972d32f9abdSBarry Smith   }
973c5d2311dSJed Brown   if (jac->type == PC_COMPOSITE_SCHUR) {
974c9c6ffaaSJed Brown     ierr = PetscOptionsGetEnum(((PetscObject)pc)->prefix,"-pc_fieldsplit_schur_factorization_type",PCFieldSplitSchurFactTypes,(PetscEnum*)&jac->schurfactorization,&flg);CHKERRQ(ierr);
975c9c6ffaaSJed Brown     if (flg) {ierr = PetscInfo(pc,"Deprecated use of -pc_fieldsplit_schur_factorization_type\n");CHKERRQ(ierr);}
976c9c6ffaaSJed Brown     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,PETSC_NULL);CHKERRQ(ierr);
977084e4875SJed Brown     ierr = PetscOptionsEnum("-pc_fieldsplit_schur_precondition","How to build preconditioner for Schur complement","PCFieldSplitSchurPrecondition",PCFieldSplitSchurPreTypes,(PetscEnum)jac->schurpre,(PetscEnum*)&jac->schurpre,PETSC_NULL);CHKERRQ(ierr);
978c5d2311dSJed Brown   }
9791b9fc7fcSBarry Smith   ierr = PetscOptionsTail();CHKERRQ(ierr);
9800971522cSBarry Smith   PetscFunctionReturn(0);
9810971522cSBarry Smith }
9820971522cSBarry Smith 
9830971522cSBarry Smith /*------------------------------------------------------------------------------------*/
9840971522cSBarry Smith 
9850971522cSBarry Smith EXTERN_C_BEGIN
9860971522cSBarry Smith #undef __FUNCT__
9870971522cSBarry Smith #define __FUNCT__ "PCFieldSplitSetFields_FieldSplit"
9885d4c12cdSJungho Lee PetscErrorCode  PCFieldSplitSetFields_FieldSplit(PC pc,const char splitname[],PetscInt n,const PetscInt *fields,const PetscInt *fields_col)
9890971522cSBarry Smith {
99097bbdb24SBarry Smith   PC_FieldSplit     *jac = (PC_FieldSplit*)pc->data;
9910971522cSBarry Smith   PetscErrorCode    ierr;
9925a9f2f41SSatish Balay   PC_FieldSplitLink ilink,next = jac->head;
99369a612a9SBarry Smith   char              prefix[128];
9945d4c12cdSJungho Lee   PetscInt          i;
9950971522cSBarry Smith 
9960971522cSBarry Smith   PetscFunctionBegin;
9976c924f48SJed Brown   if (jac->splitdefined) {
9986c924f48SJed Brown     ierr = PetscInfo1(pc,"Ignoring new split \"%s\" because the splits have already been defined\n",splitname);CHKERRQ(ierr);
9996c924f48SJed Brown     PetscFunctionReturn(0);
10006c924f48SJed Brown   }
100151f519a2SBarry Smith   for (i=0; i<n; i++) {
1002e32f2f54SBarry Smith     if (fields[i] >= jac->bs) SETERRQ2(PETSC_COMM_SELF,PETSC_ERR_ARG_OUTOFRANGE,"Field %D requested but only %D exist",fields[i],jac->bs);
1003e32f2f54SBarry Smith     if (fields[i] < 0) SETERRQ1(PETSC_COMM_SELF,PETSC_ERR_ARG_OUTOFRANGE,"Negative field %D requested",fields[i]);
100451f519a2SBarry Smith   }
1005704ba839SBarry Smith   ierr = PetscNew(struct _PC_FieldSplitLink,&ilink);CHKERRQ(ierr);
1006a04f6461SBarry Smith   if (splitname) {
1007db4c96c1SJed Brown     ierr = PetscStrallocpy(splitname,&ilink->splitname);CHKERRQ(ierr);
1008a04f6461SBarry Smith   } else {
1009a04f6461SBarry Smith     ierr = PetscMalloc(3*sizeof(char),&ilink->splitname);CHKERRQ(ierr);
1010a04f6461SBarry Smith     ierr = PetscSNPrintf(ilink->splitname,2,"%s",jac->nsplits);CHKERRQ(ierr);
1011a04f6461SBarry Smith   }
1012704ba839SBarry Smith   ierr = PetscMalloc(n*sizeof(PetscInt),&ilink->fields);CHKERRQ(ierr);
10135a9f2f41SSatish Balay   ierr = PetscMemcpy(ilink->fields,fields,n*sizeof(PetscInt));CHKERRQ(ierr);
10145d4c12cdSJungho Lee   ierr = PetscMalloc(n*sizeof(PetscInt),&ilink->fields_col);CHKERRQ(ierr);
10155d4c12cdSJungho Lee   ierr = PetscMemcpy(ilink->fields_col,fields_col,n*sizeof(PetscInt));CHKERRQ(ierr);
10165a9f2f41SSatish Balay   ilink->nfields = n;
10175a9f2f41SSatish Balay   ilink->next    = PETSC_NULL;
10187adad957SLisandro Dalcin   ierr           = KSPCreate(((PetscObject)pc)->comm,&ilink->ksp);CHKERRQ(ierr);
10191cee3971SBarry Smith   ierr           = PetscObjectIncrementTabLevel((PetscObject)ilink->ksp,(PetscObject)pc,1);CHKERRQ(ierr);
10205a9f2f41SSatish Balay   ierr           = KSPSetType(ilink->ksp,KSPPREONLY);CHKERRQ(ierr);
10219005cf84SBarry Smith   ierr           = PetscLogObjectParent((PetscObject)pc,(PetscObject)ilink->ksp);CHKERRQ(ierr);
102269a612a9SBarry Smith 
1023a04f6461SBarry Smith   ierr = PetscSNPrintf(prefix,sizeof prefix,"%sfieldsplit_%s_",((PetscObject)pc)->prefix?((PetscObject)pc)->prefix:"",ilink->splitname);CHKERRQ(ierr);
10245a9f2f41SSatish Balay   ierr = KSPSetOptionsPrefix(ilink->ksp,prefix);CHKERRQ(ierr);
10250971522cSBarry Smith 
10260971522cSBarry Smith   if (!next) {
10275a9f2f41SSatish Balay     jac->head       = ilink;
102851f519a2SBarry Smith     ilink->previous = PETSC_NULL;
10290971522cSBarry Smith   } else {
10300971522cSBarry Smith     while (next->next) {
10310971522cSBarry Smith       next = next->next;
10320971522cSBarry Smith     }
10335a9f2f41SSatish Balay     next->next      = ilink;
103451f519a2SBarry Smith     ilink->previous = next;
10350971522cSBarry Smith   }
10360971522cSBarry Smith   jac->nsplits++;
10370971522cSBarry Smith   PetscFunctionReturn(0);
10380971522cSBarry Smith }
10390971522cSBarry Smith EXTERN_C_END
10400971522cSBarry Smith 
1041e69d4d44SBarry Smith EXTERN_C_BEGIN
1042e69d4d44SBarry Smith #undef __FUNCT__
1043e69d4d44SBarry Smith #define __FUNCT__ "PCFieldSplitGetSubKSP_FieldSplit_Schur"
10447087cfbeSBarry Smith PetscErrorCode  PCFieldSplitGetSubKSP_FieldSplit_Schur(PC pc,PetscInt *n,KSP **subksp)
1045e69d4d44SBarry Smith {
1046e69d4d44SBarry Smith   PC_FieldSplit *jac = (PC_FieldSplit*)pc->data;
1047e69d4d44SBarry Smith   PetscErrorCode ierr;
1048e69d4d44SBarry Smith 
1049e69d4d44SBarry Smith   PetscFunctionBegin;
1050519d70e2SJed Brown   ierr = PetscMalloc(jac->nsplits*sizeof(KSP),subksp);CHKERRQ(ierr);
1051e69d4d44SBarry Smith   ierr = MatSchurComplementGetKSP(jac->schur,*subksp);CHKERRQ(ierr);
1052e69d4d44SBarry Smith   (*subksp)[1] = jac->kspschur;
105313e0d083SBarry Smith   if (n) *n = jac->nsplits;
1054e69d4d44SBarry Smith   PetscFunctionReturn(0);
1055e69d4d44SBarry Smith }
1056e69d4d44SBarry Smith EXTERN_C_END
10570971522cSBarry Smith 
10580971522cSBarry Smith EXTERN_C_BEGIN
10590971522cSBarry Smith #undef __FUNCT__
106069a612a9SBarry Smith #define __FUNCT__ "PCFieldSplitGetSubKSP_FieldSplit"
10617087cfbeSBarry Smith PetscErrorCode  PCFieldSplitGetSubKSP_FieldSplit(PC pc,PetscInt *n,KSP **subksp)
10620971522cSBarry Smith {
10630971522cSBarry Smith   PC_FieldSplit     *jac = (PC_FieldSplit*)pc->data;
10640971522cSBarry Smith   PetscErrorCode    ierr;
10650971522cSBarry Smith   PetscInt          cnt = 0;
10665a9f2f41SSatish Balay   PC_FieldSplitLink ilink = jac->head;
10670971522cSBarry Smith 
10680971522cSBarry Smith   PetscFunctionBegin;
10695d480477SMatthew G Knepley   ierr = PetscMalloc(jac->nsplits*sizeof(KSP),subksp);CHKERRQ(ierr);
10705a9f2f41SSatish Balay   while (ilink) {
10715a9f2f41SSatish Balay     (*subksp)[cnt++] = ilink->ksp;
10725a9f2f41SSatish Balay     ilink = ilink->next;
10730971522cSBarry Smith   }
10745d480477SMatthew G Knepley   if (cnt != jac->nsplits) SETERRQ2(PETSC_COMM_SELF,PETSC_ERR_PLIB,"Corrupt PCFIELDSPLIT object: number of splits in linked list %D does not match number in object %D",cnt,jac->nsplits);
107513e0d083SBarry Smith   if (n) *n = jac->nsplits;
10760971522cSBarry Smith   PetscFunctionReturn(0);
10770971522cSBarry Smith }
10780971522cSBarry Smith EXTERN_C_END
10790971522cSBarry Smith 
1080704ba839SBarry Smith EXTERN_C_BEGIN
1081704ba839SBarry Smith #undef __FUNCT__
1082704ba839SBarry Smith #define __FUNCT__ "PCFieldSplitSetIS_FieldSplit"
10837087cfbeSBarry Smith PetscErrorCode  PCFieldSplitSetIS_FieldSplit(PC pc,const char splitname[],IS is)
1084704ba839SBarry Smith {
1085704ba839SBarry Smith   PC_FieldSplit     *jac = (PC_FieldSplit*)pc->data;
1086704ba839SBarry Smith   PetscErrorCode    ierr;
1087704ba839SBarry Smith   PC_FieldSplitLink ilink, next = jac->head;
1088704ba839SBarry Smith   char              prefix[128];
1089704ba839SBarry Smith 
1090704ba839SBarry Smith   PetscFunctionBegin;
10916c924f48SJed Brown   if (jac->splitdefined) {
10926c924f48SJed Brown     ierr = PetscInfo1(pc,"Ignoring new split \"%s\" because the splits have already been defined\n",splitname);CHKERRQ(ierr);
10936c924f48SJed Brown     PetscFunctionReturn(0);
10946c924f48SJed Brown   }
109516913363SBarry Smith   ierr = PetscNew(struct _PC_FieldSplitLink,&ilink);CHKERRQ(ierr);
1096a04f6461SBarry Smith   if (splitname) {
1097db4c96c1SJed Brown     ierr = PetscStrallocpy(splitname,&ilink->splitname);CHKERRQ(ierr);
1098a04f6461SBarry Smith   } else {
1099b5787286SJed Brown     ierr = PetscMalloc(8*sizeof(char),&ilink->splitname);CHKERRQ(ierr);
1100b5787286SJed Brown     ierr = PetscSNPrintf(ilink->splitname,7,"%D",jac->nsplits);CHKERRQ(ierr);
1101a04f6461SBarry Smith   }
11021ab39975SBarry Smith   ierr = PetscObjectReference((PetscObject)is);CHKERRQ(ierr);
1103b5787286SJed Brown   ierr = ISDestroy(&ilink->is);CHKERRQ(ierr);
1104b5787286SJed Brown   ilink->is      = is;
1105b5787286SJed Brown   ierr = PetscObjectReference((PetscObject)is);CHKERRQ(ierr);
1106b5787286SJed Brown   ierr = ISDestroy(&ilink->is_col);CHKERRQ(ierr);
1107b5787286SJed Brown   ilink->is_col  = is;
1108704ba839SBarry Smith   ilink->next    = PETSC_NULL;
1109704ba839SBarry Smith   ierr           = KSPCreate(((PetscObject)pc)->comm,&ilink->ksp);CHKERRQ(ierr);
11101cee3971SBarry Smith   ierr           = PetscObjectIncrementTabLevel((PetscObject)ilink->ksp,(PetscObject)pc,1);CHKERRQ(ierr);
1111704ba839SBarry Smith   ierr           = KSPSetType(ilink->ksp,KSPPREONLY);CHKERRQ(ierr);
11129005cf84SBarry Smith   ierr           = PetscLogObjectParent((PetscObject)pc,(PetscObject)ilink->ksp);CHKERRQ(ierr);
1113704ba839SBarry Smith 
1114a04f6461SBarry Smith   ierr = PetscSNPrintf(prefix,sizeof prefix,"%sfieldsplit_%s_",((PetscObject)pc)->prefix?((PetscObject)pc)->prefix:"",ilink->splitname);CHKERRQ(ierr);
1115704ba839SBarry Smith   ierr = KSPSetOptionsPrefix(ilink->ksp,prefix);CHKERRQ(ierr);
1116704ba839SBarry Smith 
1117704ba839SBarry Smith   if (!next) {
1118704ba839SBarry Smith     jac->head       = ilink;
1119704ba839SBarry Smith     ilink->previous = PETSC_NULL;
1120704ba839SBarry Smith   } else {
1121704ba839SBarry Smith     while (next->next) {
1122704ba839SBarry Smith       next = next->next;
1123704ba839SBarry Smith     }
1124704ba839SBarry Smith     next->next      = ilink;
1125704ba839SBarry Smith     ilink->previous = next;
1126704ba839SBarry Smith   }
1127704ba839SBarry Smith   jac->nsplits++;
1128704ba839SBarry Smith 
1129704ba839SBarry Smith   PetscFunctionReturn(0);
1130704ba839SBarry Smith }
1131704ba839SBarry Smith EXTERN_C_END
1132704ba839SBarry Smith 
11330971522cSBarry Smith #undef __FUNCT__
11340971522cSBarry Smith #define __FUNCT__ "PCFieldSplitSetFields"
11350971522cSBarry Smith /*@
11360971522cSBarry Smith     PCFieldSplitSetFields - Sets the fields for one particular split in the field split preconditioner
11370971522cSBarry Smith 
1138ad4df100SBarry Smith     Logically Collective on PC
11390971522cSBarry Smith 
11400971522cSBarry Smith     Input Parameters:
11410971522cSBarry Smith +   pc  - the preconditioner context
1142a04f6461SBarry Smith .   splitname - name of this split, if PETSC_NULL the number of the split is used
11430971522cSBarry Smith .   n - the number of fields in this split
1144db4c96c1SJed Brown -   fields - the fields in this split
11450971522cSBarry Smith 
11460971522cSBarry Smith     Level: intermediate
11470971522cSBarry Smith 
1148d32f9abdSBarry Smith     Notes: Use PCFieldSplitSetIS() to set a completely general set of indices as a field.
1149d32f9abdSBarry Smith 
1150d32f9abdSBarry Smith      The PCFieldSplitSetFields() is for defining fields as a strided blocks. For example, if the block
1151d32f9abdSBarry 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
1152d32f9abdSBarry Smith      0xx3xx6xx9xx12 ... x1xx4xx7xx ... xx2xx5xx8xx.. 01x34x67x... 0x1x3x5x7.. x12x45x78x....
1153d32f9abdSBarry Smith      where the numbered entries indicate what is in the field.
1154d32f9abdSBarry Smith 
1155db4c96c1SJed Brown      This function is called once per split (it creates a new split each time).  Solve options
1156db4c96c1SJed Brown      for this split will be available under the prefix -fieldsplit_SPLITNAME_.
1157db4c96c1SJed Brown 
11585d4c12cdSJungho Lee      Developer Note: This routine does not actually create the IS representing the split, that is delayed
11595d4c12cdSJungho Lee      until PCSetUp_FieldSplit(), because information about the vector/matrix layouts may not be
11605d4c12cdSJungho Lee      available when this routine is called.
11615d4c12cdSJungho Lee 
1162d32f9abdSBarry Smith .seealso: PCFieldSplitGetSubKSP(), PCFIELDSPLIT, PCFieldSplitSetBlockSize(), PCFieldSplitSetIS()
11630971522cSBarry Smith 
11640971522cSBarry Smith @*/
11655d4c12cdSJungho Lee PetscErrorCode  PCFieldSplitSetFields(PC pc,const char splitname[],PetscInt n,const PetscInt *fields,const PetscInt *fields_col)
11660971522cSBarry Smith {
11674ac538c5SBarry Smith   PetscErrorCode ierr;
11680971522cSBarry Smith 
11690971522cSBarry Smith   PetscFunctionBegin;
11700700a824SBarry Smith   PetscValidHeaderSpecific(pc,PC_CLASSID,1);
1171db4c96c1SJed Brown   PetscValidCharPointer(splitname,2);
1172db4c96c1SJed Brown   if (n < 1) SETERRQ2(((PetscObject)pc)->comm,PETSC_ERR_ARG_OUTOFRANGE,"Provided number of fields %D in split \"%s\" not positive",n,splitname);
1173db4c96c1SJed Brown   PetscValidIntPointer(fields,3);
11745d4c12cdSJungho Lee   ierr = PetscTryMethod(pc,"PCFieldSplitSetFields_C",(PC,const char[],PetscInt,const PetscInt *,const PetscInt *),(pc,splitname,n,fields,fields_col));CHKERRQ(ierr);
11750971522cSBarry Smith   PetscFunctionReturn(0);
11760971522cSBarry Smith }
11770971522cSBarry Smith 
11780971522cSBarry Smith #undef __FUNCT__
1179704ba839SBarry Smith #define __FUNCT__ "PCFieldSplitSetIS"
1180704ba839SBarry Smith /*@
1181704ba839SBarry Smith     PCFieldSplitSetIS - Sets the exact elements for field
1182704ba839SBarry Smith 
1183ad4df100SBarry Smith     Logically Collective on PC
1184704ba839SBarry Smith 
1185704ba839SBarry Smith     Input Parameters:
1186704ba839SBarry Smith +   pc  - the preconditioner context
1187a04f6461SBarry Smith .   splitname - name of this split, if PETSC_NULL the number of the split is used
1188db4c96c1SJed Brown -   is - the index set that defines the vector elements in this field
1189704ba839SBarry Smith 
1190d32f9abdSBarry Smith 
1191a6ffb8dbSJed Brown     Notes:
1192a6ffb8dbSJed Brown     Use PCFieldSplitSetFields(), for fields defined by strided types.
1193a6ffb8dbSJed Brown 
1194db4c96c1SJed Brown     This function is called once per split (it creates a new split each time).  Solve options
1195db4c96c1SJed Brown     for this split will be available under the prefix -fieldsplit_SPLITNAME_.
1196d32f9abdSBarry Smith 
1197704ba839SBarry Smith     Level: intermediate
1198704ba839SBarry Smith 
1199704ba839SBarry Smith .seealso: PCFieldSplitGetSubKSP(), PCFIELDSPLIT, PCFieldSplitSetBlockSize()
1200704ba839SBarry Smith 
1201704ba839SBarry Smith @*/
12027087cfbeSBarry Smith PetscErrorCode  PCFieldSplitSetIS(PC pc,const char splitname[],IS is)
1203704ba839SBarry Smith {
12044ac538c5SBarry Smith   PetscErrorCode ierr;
1205704ba839SBarry Smith 
1206704ba839SBarry Smith   PetscFunctionBegin;
12070700a824SBarry Smith   PetscValidHeaderSpecific(pc,PC_CLASSID,1);
12087b62db95SJungho Lee   if (splitname) PetscValidCharPointer(splitname,2);
1209db4c96c1SJed Brown   PetscValidHeaderSpecific(is,IS_CLASSID,3);
12104ac538c5SBarry Smith   ierr = PetscTryMethod(pc,"PCFieldSplitSetIS_C",(PC,const char[],IS),(pc,splitname,is));CHKERRQ(ierr);
1211704ba839SBarry Smith   PetscFunctionReturn(0);
1212704ba839SBarry Smith }
1213704ba839SBarry Smith 
1214704ba839SBarry Smith #undef __FUNCT__
121557a9adfeSMatthew G Knepley #define __FUNCT__ "PCFieldSplitGetIS"
121657a9adfeSMatthew G Knepley /*@
121757a9adfeSMatthew G Knepley     PCFieldSplitGetIS - Retrieves the elements for a field as an IS
121857a9adfeSMatthew G Knepley 
121957a9adfeSMatthew G Knepley     Logically Collective on PC
122057a9adfeSMatthew G Knepley 
122157a9adfeSMatthew G Knepley     Input Parameters:
122257a9adfeSMatthew G Knepley +   pc  - the preconditioner context
122357a9adfeSMatthew G Knepley -   splitname - name of this split
122457a9adfeSMatthew G Knepley 
122557a9adfeSMatthew G Knepley     Output Parameter:
122657a9adfeSMatthew G Knepley -   is - the index set that defines the vector elements in this field, or PETSC_NULL if the field is not found
122757a9adfeSMatthew G Knepley 
122857a9adfeSMatthew G Knepley     Level: intermediate
122957a9adfeSMatthew G Knepley 
123057a9adfeSMatthew G Knepley .seealso: PCFieldSplitGetSubKSP(), PCFIELDSPLIT, PCFieldSplitSetIS()
123157a9adfeSMatthew G Knepley 
123257a9adfeSMatthew G Knepley @*/
123357a9adfeSMatthew G Knepley PetscErrorCode PCFieldSplitGetIS(PC pc,const char splitname[],IS *is)
123457a9adfeSMatthew G Knepley {
123557a9adfeSMatthew G Knepley   PetscErrorCode ierr;
123657a9adfeSMatthew G Knepley 
123757a9adfeSMatthew G Knepley   PetscFunctionBegin;
123857a9adfeSMatthew G Knepley   PetscValidHeaderSpecific(pc,PC_CLASSID,1);
123957a9adfeSMatthew G Knepley   PetscValidCharPointer(splitname,2);
124057a9adfeSMatthew G Knepley   PetscValidPointer(is,3);
124157a9adfeSMatthew G Knepley   {
124257a9adfeSMatthew G Knepley     PC_FieldSplit    *jac   = (PC_FieldSplit *) pc->data;
124357a9adfeSMatthew G Knepley     PC_FieldSplitLink ilink = jac->head;
124457a9adfeSMatthew G Knepley     PetscBool         found;
124557a9adfeSMatthew G Knepley 
124657a9adfeSMatthew G Knepley     *is = PETSC_NULL;
124757a9adfeSMatthew G Knepley     while(ilink) {
124857a9adfeSMatthew G Knepley       ierr = PetscStrcmp(ilink->splitname, splitname, &found);CHKERRQ(ierr);
124957a9adfeSMatthew G Knepley       if (found) {
125057a9adfeSMatthew G Knepley         *is = ilink->is;
125157a9adfeSMatthew G Knepley         break;
125257a9adfeSMatthew G Knepley       }
125357a9adfeSMatthew G Knepley       ilink = ilink->next;
125457a9adfeSMatthew G Knepley     }
125557a9adfeSMatthew G Knepley   }
125657a9adfeSMatthew G Knepley   PetscFunctionReturn(0);
125757a9adfeSMatthew G Knepley }
125857a9adfeSMatthew G Knepley 
125957a9adfeSMatthew G Knepley #undef __FUNCT__
126051f519a2SBarry Smith #define __FUNCT__ "PCFieldSplitSetBlockSize"
126151f519a2SBarry Smith /*@
126251f519a2SBarry Smith     PCFieldSplitSetBlockSize - Sets the block size for defining where fields start in the
126351f519a2SBarry Smith       fieldsplit preconditioner. If not set the matrix block size is used.
126451f519a2SBarry Smith 
1265ad4df100SBarry Smith     Logically Collective on PC
126651f519a2SBarry Smith 
126751f519a2SBarry Smith     Input Parameters:
126851f519a2SBarry Smith +   pc  - the preconditioner context
126951f519a2SBarry Smith -   bs - the block size
127051f519a2SBarry Smith 
127151f519a2SBarry Smith     Level: intermediate
127251f519a2SBarry Smith 
127351f519a2SBarry Smith .seealso: PCFieldSplitGetSubKSP(), PCFIELDSPLIT, PCFieldSplitSetFields()
127451f519a2SBarry Smith 
127551f519a2SBarry Smith @*/
12767087cfbeSBarry Smith PetscErrorCode  PCFieldSplitSetBlockSize(PC pc,PetscInt bs)
127751f519a2SBarry Smith {
12784ac538c5SBarry Smith   PetscErrorCode ierr;
127951f519a2SBarry Smith 
128051f519a2SBarry Smith   PetscFunctionBegin;
12810700a824SBarry Smith   PetscValidHeaderSpecific(pc,PC_CLASSID,1);
1282c5eb9154SBarry Smith   PetscValidLogicalCollectiveInt(pc,bs,2);
12834ac538c5SBarry Smith   ierr = PetscTryMethod(pc,"PCFieldSplitSetBlockSize_C",(PC,PetscInt),(pc,bs));CHKERRQ(ierr);
128451f519a2SBarry Smith   PetscFunctionReturn(0);
128551f519a2SBarry Smith }
128651f519a2SBarry Smith 
128751f519a2SBarry Smith #undef __FUNCT__
128869a612a9SBarry Smith #define __FUNCT__ "PCFieldSplitGetSubKSP"
12890971522cSBarry Smith /*@C
129069a612a9SBarry Smith    PCFieldSplitGetSubKSP - Gets the KSP contexts for all splits
12910971522cSBarry Smith 
129269a612a9SBarry Smith    Collective on KSP
12930971522cSBarry Smith 
12940971522cSBarry Smith    Input Parameter:
12950971522cSBarry Smith .  pc - the preconditioner context
12960971522cSBarry Smith 
12970971522cSBarry Smith    Output Parameters:
129813e0d083SBarry Smith +  n - the number of splits
129969a612a9SBarry Smith -  pc - the array of KSP contexts
13000971522cSBarry Smith 
13010971522cSBarry Smith    Note:
1302d32f9abdSBarry Smith    After PCFieldSplitGetSubKSP() the array of KSPs IS to be freed by the user
1303d32f9abdSBarry Smith    (not the KSP just the array that contains them).
13040971522cSBarry Smith 
130569a612a9SBarry Smith    You must call KSPSetUp() before calling PCFieldSplitGetSubKSP().
13060971522cSBarry Smith 
13070971522cSBarry Smith    Level: advanced
13080971522cSBarry Smith 
13090971522cSBarry Smith .seealso: PCFIELDSPLIT
13100971522cSBarry Smith @*/
13117087cfbeSBarry Smith PetscErrorCode  PCFieldSplitGetSubKSP(PC pc,PetscInt *n,KSP *subksp[])
13120971522cSBarry Smith {
13134ac538c5SBarry Smith   PetscErrorCode ierr;
13140971522cSBarry Smith 
13150971522cSBarry Smith   PetscFunctionBegin;
13160700a824SBarry Smith   PetscValidHeaderSpecific(pc,PC_CLASSID,1);
131713e0d083SBarry Smith   if (n) PetscValidIntPointer(n,2);
13184ac538c5SBarry Smith   ierr = PetscUseMethod(pc,"PCFieldSplitGetSubKSP_C",(PC,PetscInt*,KSP **),(pc,n,subksp));CHKERRQ(ierr);
13190971522cSBarry Smith   PetscFunctionReturn(0);
13200971522cSBarry Smith }
13210971522cSBarry Smith 
1322e69d4d44SBarry Smith #undef __FUNCT__
1323e69d4d44SBarry Smith #define __FUNCT__ "PCFieldSplitSchurPrecondition"
1324e69d4d44SBarry Smith /*@
1325e69d4d44SBarry Smith     PCFieldSplitSchurPrecondition -  Indicates if the Schur complement is preconditioned by a preconditioner constructed by the
1326a04f6461SBarry Smith       A11 matrix. Otherwise no preconditioner is used.
1327e69d4d44SBarry Smith 
1328e69d4d44SBarry Smith     Collective on PC
1329e69d4d44SBarry Smith 
1330e69d4d44SBarry Smith     Input Parameters:
1331e69d4d44SBarry Smith +   pc  - the preconditioner context
1332fd1303e9SJungho Lee .   ptype - which matrix to use for preconditioning the Schur complement, PC_FIELDSPLIT_SCHUR_PRE_DIAG (diag) is default
1333084e4875SJed Brown -   userpre - matrix to use for preconditioning, or PETSC_NULL
1334084e4875SJed Brown 
1335e69d4d44SBarry Smith     Options Database:
1336084e4875SJed Brown .     -pc_fieldsplit_schur_precondition <self,user,diag> default is diag
1337e69d4d44SBarry Smith 
1338fd1303e9SJungho Lee     Notes:
1339fd1303e9SJungho Lee $    If ptype is
1340fd1303e9SJungho Lee $        user then the preconditioner for the Schur complement is generated by the provided matrix (pre argument
1341fd1303e9SJungho Lee $             to this function).
1342fd1303e9SJungho Lee $        diag then the preconditioner for the Schur complement is generated by the block diagonal part of the original
1343fd1303e9SJungho Lee $             matrix associated with the Schur complement (i.e. A11)
1344fd1303e9SJungho Lee $        self the preconditioner for the Schur complement is generated from the Schur complement matrix itself:
1345fd1303e9SJungho Lee $             The only preconditioner that currently works directly with the Schur complement matrix object is the PCLSC
1346fd1303e9SJungho Lee $             preconditioner
1347fd1303e9SJungho Lee 
1348fd1303e9SJungho Lee      When solving a saddle point problem, where the A11 block is identically zero, using diag as the ptype only makes sense
1349fd1303e9SJungho Lee     with the additional option -fieldsplit_1_pc_type none. Usually for saddle point problems one would use a ptype of self and
1350fd1303e9SJungho Lee     -fieldsplit_1_pc_type lsc which uses the least squares commutator compute a preconditioner for the Schur complement.
1351fd1303e9SJungho Lee 
1352fd1303e9SJungho Lee     Developer Notes: This is a terrible name, gives no good indication of what the function does and should also have Set in
1353fd1303e9SJungho Lee      the name since it sets a proceedure to use.
1354fd1303e9SJungho Lee 
1355e69d4d44SBarry Smith     Level: intermediate
1356e69d4d44SBarry Smith 
1357fd1303e9SJungho Lee .seealso: PCFieldSplitGetSubKSP(), PCFIELDSPLIT, PCFieldSplitSetFields(), PCFieldSplitSchurPreType, PCLSC
1358e69d4d44SBarry Smith 
1359e69d4d44SBarry Smith @*/
13607087cfbeSBarry Smith PetscErrorCode  PCFieldSplitSchurPrecondition(PC pc,PCFieldSplitSchurPreType ptype,Mat pre)
1361e69d4d44SBarry Smith {
13624ac538c5SBarry Smith   PetscErrorCode ierr;
1363e69d4d44SBarry Smith 
1364e69d4d44SBarry Smith   PetscFunctionBegin;
13650700a824SBarry Smith   PetscValidHeaderSpecific(pc,PC_CLASSID,1);
13664ac538c5SBarry Smith   ierr = PetscTryMethod(pc,"PCFieldSplitSchurPrecondition_C",(PC,PCFieldSplitSchurPreType,Mat),(pc,ptype,pre));CHKERRQ(ierr);
1367e69d4d44SBarry Smith   PetscFunctionReturn(0);
1368e69d4d44SBarry Smith }
1369e69d4d44SBarry Smith 
1370e69d4d44SBarry Smith EXTERN_C_BEGIN
1371e69d4d44SBarry Smith #undef __FUNCT__
1372e69d4d44SBarry Smith #define __FUNCT__ "PCFieldSplitSchurPrecondition_FieldSplit"
13737087cfbeSBarry Smith PetscErrorCode  PCFieldSplitSchurPrecondition_FieldSplit(PC pc,PCFieldSplitSchurPreType ptype,Mat pre)
1374e69d4d44SBarry Smith {
1375e69d4d44SBarry Smith   PC_FieldSplit  *jac = (PC_FieldSplit*)pc->data;
1376084e4875SJed Brown   PetscErrorCode  ierr;
1377e69d4d44SBarry Smith 
1378e69d4d44SBarry Smith   PetscFunctionBegin;
1379084e4875SJed Brown   jac->schurpre = ptype;
1380084e4875SJed Brown   if (pre) {
13816bf464f9SBarry Smith     ierr = MatDestroy(&jac->schur_user);CHKERRQ(ierr);
1382084e4875SJed Brown     jac->schur_user = pre;
1383084e4875SJed Brown     ierr = PetscObjectReference((PetscObject)jac->schur_user);CHKERRQ(ierr);
1384084e4875SJed Brown   }
1385e69d4d44SBarry Smith   PetscFunctionReturn(0);
1386e69d4d44SBarry Smith }
1387e69d4d44SBarry Smith EXTERN_C_END
1388e69d4d44SBarry Smith 
138930ad9308SMatthew Knepley #undef __FUNCT__
1390c9c6ffaaSJed Brown #define __FUNCT__ "PCFieldSplitSetSchurFactType"
1391ab1df9f5SJed Brown /*@
1392c9c6ffaaSJed Brown     PCFieldSplitSetSchurFactType -  sets which blocks of the approximate block factorization to retain
1393ab1df9f5SJed Brown 
1394ab1df9f5SJed Brown     Collective on PC
1395ab1df9f5SJed Brown 
1396ab1df9f5SJed Brown     Input Parameters:
1397ab1df9f5SJed Brown +   pc  - the preconditioner context
1398c9c6ffaaSJed Brown -   ftype - which blocks of factorization to retain, PC_FIELDSPLIT_SCHUR_FACT_FULL is default
1399ab1df9f5SJed Brown 
1400ab1df9f5SJed Brown     Options Database:
1401c9c6ffaaSJed Brown .     -pc_fieldsplit_schur_fact_type <diag,lower,upper,full> default is full
1402ab1df9f5SJed Brown 
1403ab1df9f5SJed Brown 
1404ab1df9f5SJed Brown     Level: intermediate
1405ab1df9f5SJed Brown 
1406ab1df9f5SJed Brown     Notes:
1407ab1df9f5SJed Brown     The FULL factorization is
1408ab1df9f5SJed Brown 
1409ab1df9f5SJed Brown $   (A   B)  = (1       0) (A   0) (1  Ainv*B)
1410ab1df9f5SJed Brown $   (C   D)    (C*Ainv  1) (0   S) (0     1  )
1411ab1df9f5SJed Brown 
14126be4592eSBarry Smith     where S = D - 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,
14136be4592eSBarry Smith     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).
1414ab1df9f5SJed Brown 
14156be4592eSBarry Smith     If applied exactly, FULL factorization is a direct solver. The preconditioned operator with LOWER or UPPER has all eigenvalues equal to 1 and minimal polynomial
14166be4592eSBarry Smith     of degree 2, so KSPGMRES converges in 2 iterations. If the iteration count is very low, consider using KSPFGMRES or KSPGCR which can use one less preconditioner
14176be4592eSBarry 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. With DIAG,
14186be4592eSBarry Smith     the preconditioned operator has three distinct nonzero eigenvalues and minimal polynomial of degree at most 4, so KSPGMRES converges in at most 4 iterations.
1419ab1df9f5SJed Brown 
14206be4592eSBarry Smith     For symmetric problems in which A is positive definite and S is negative definite, DIAG can be used with KSPMINRES. Note that a flexible method like KSPFGMRES
14216be4592eSBarry Smith     or KSPGCR must be used if the fieldsplit preconditioner is nonlinear (e.g. a few iterations of a Krylov method is used inside a split).
1422ab1df9f5SJed Brown 
1423ab1df9f5SJed Brown     References:
1424ab1df9f5SJed Brown     Murphy, Golub, and Wathen, A note on preconditioning indefinite linear systems, SIAM J. Sci. Comput., 21 (2000) pp. 1969-1972.
1425ab1df9f5SJed Brown 
1426ab1df9f5SJed Brown     Ipsen, A note on preconditioning nonsymmetric matrices, SIAM J. Sci. Comput., 23 (2001), pp. 1050-1051.
1427ab1df9f5SJed Brown 
1428ab1df9f5SJed Brown .seealso: PCFieldSplitGetSubKSP(), PCFIELDSPLIT, PCFieldSplitSetFields(), PCFieldSplitSchurPreType
1429ab1df9f5SJed Brown @*/
1430c9c6ffaaSJed Brown PetscErrorCode  PCFieldSplitSetSchurFactType(PC pc,PCFieldSplitSchurFactType ftype)
1431ab1df9f5SJed Brown {
1432ab1df9f5SJed Brown   PetscErrorCode ierr;
1433ab1df9f5SJed Brown 
1434ab1df9f5SJed Brown   PetscFunctionBegin;
1435ab1df9f5SJed Brown   PetscValidHeaderSpecific(pc,PC_CLASSID,1);
1436c9c6ffaaSJed Brown   ierr = PetscTryMethod(pc,"PCFieldSplitSetSchurFactType_C",(PC,PCFieldSplitSchurFactType),(pc,ftype));CHKERRQ(ierr);
1437ab1df9f5SJed Brown   PetscFunctionReturn(0);
1438ab1df9f5SJed Brown }
1439ab1df9f5SJed Brown 
1440ab1df9f5SJed Brown #undef __FUNCT__
1441c9c6ffaaSJed Brown #define __FUNCT__ "PCFieldSplitSetSchurFactType_FieldSplit"
1442c9c6ffaaSJed Brown PETSC_EXTERN_C PetscErrorCode PCFieldSplitSetSchurFactType_FieldSplit(PC pc,PCFieldSplitSchurFactType ftype)
1443ab1df9f5SJed Brown {
1444ab1df9f5SJed Brown   PC_FieldSplit  *jac = (PC_FieldSplit*)pc->data;
1445ab1df9f5SJed Brown 
1446ab1df9f5SJed Brown   PetscFunctionBegin;
1447ab1df9f5SJed Brown   jac->schurfactorization = ftype;
1448ab1df9f5SJed Brown   PetscFunctionReturn(0);
1449ab1df9f5SJed Brown }
1450ab1df9f5SJed Brown 
1451ab1df9f5SJed Brown #undef __FUNCT__
145230ad9308SMatthew Knepley #define __FUNCT__ "PCFieldSplitGetSchurBlocks"
145330ad9308SMatthew Knepley /*@C
14548c03b21aSDmitry Karpeev    PCFieldSplitGetSchurBlocks - Gets all matrix blocks for the Schur complement
145530ad9308SMatthew Knepley 
145630ad9308SMatthew Knepley    Collective on KSP
145730ad9308SMatthew Knepley 
145830ad9308SMatthew Knepley    Input Parameter:
145930ad9308SMatthew Knepley .  pc - the preconditioner context
146030ad9308SMatthew Knepley 
146130ad9308SMatthew Knepley    Output Parameters:
1462a04f6461SBarry Smith +  A00 - the (0,0) block
1463a04f6461SBarry Smith .  A01 - the (0,1) block
1464a04f6461SBarry Smith .  A10 - the (1,0) block
1465a04f6461SBarry Smith -  A11 - the (1,1) block
146630ad9308SMatthew Knepley 
146730ad9308SMatthew Knepley    Level: advanced
146830ad9308SMatthew Knepley 
146930ad9308SMatthew Knepley .seealso: PCFIELDSPLIT
147030ad9308SMatthew Knepley @*/
1471a04f6461SBarry Smith PetscErrorCode  PCFieldSplitGetSchurBlocks(PC pc,Mat *A00,Mat *A01,Mat *A10, Mat *A11)
147230ad9308SMatthew Knepley {
147330ad9308SMatthew Knepley   PC_FieldSplit *jac = (PC_FieldSplit *) pc->data;
147430ad9308SMatthew Knepley 
147530ad9308SMatthew Knepley   PetscFunctionBegin;
14760700a824SBarry Smith   PetscValidHeaderSpecific(pc,PC_CLASSID,1);
1477c1235816SBarry Smith   if (jac->type != PC_COMPOSITE_SCHUR) SETERRQ(((PetscObject)pc)->comm,PETSC_ERR_ARG_WRONG, "FieldSplit is not using a Schur complement approach.");
1478a04f6461SBarry Smith   if (A00) *A00 = jac->pmat[0];
1479a04f6461SBarry Smith   if (A01) *A01 = jac->B;
1480a04f6461SBarry Smith   if (A10) *A10 = jac->C;
1481a04f6461SBarry Smith   if (A11) *A11 = jac->pmat[1];
148230ad9308SMatthew Knepley   PetscFunctionReturn(0);
148330ad9308SMatthew Knepley }
148430ad9308SMatthew Knepley 
148579416396SBarry Smith EXTERN_C_BEGIN
148679416396SBarry Smith #undef __FUNCT__
148779416396SBarry Smith #define __FUNCT__ "PCFieldSplitSetType_FieldSplit"
14887087cfbeSBarry Smith PetscErrorCode  PCFieldSplitSetType_FieldSplit(PC pc,PCCompositeType type)
148979416396SBarry Smith {
149079416396SBarry Smith   PC_FieldSplit  *jac = (PC_FieldSplit*)pc->data;
1491e69d4d44SBarry Smith   PetscErrorCode ierr;
149279416396SBarry Smith 
149379416396SBarry Smith   PetscFunctionBegin;
149479416396SBarry Smith   jac->type = type;
14953b224e63SBarry Smith   if (type == PC_COMPOSITE_SCHUR) {
14963b224e63SBarry Smith     pc->ops->apply = PCApply_FieldSplit_Schur;
14973b224e63SBarry Smith     pc->ops->view  = PCView_FieldSplit_Schur;
1498e69d4d44SBarry Smith     ierr = PetscObjectComposeFunctionDynamic((PetscObject)pc,"PCFieldSplitGetSubKSP_C","PCFieldSplitGetSubKSP_FieldSplit_Schur",PCFieldSplitGetSubKSP_FieldSplit_Schur);CHKERRQ(ierr);
1499e69d4d44SBarry Smith     ierr = PetscObjectComposeFunctionDynamic((PetscObject)pc,"PCFieldSplitSchurPrecondition_C","PCFieldSplitSchurPrecondition_FieldSplit",PCFieldSplitSchurPrecondition_FieldSplit);CHKERRQ(ierr);
1500c9c6ffaaSJed Brown     ierr = PetscObjectComposeFunctionDynamic((PetscObject)pc,"PCFieldSplitSetSchurFactType_C","PCFieldSplitSetSchurFactType_FieldSplit",PCFieldSplitSetSchurFactType_FieldSplit);CHKERRQ(ierr);
1501e69d4d44SBarry Smith 
15023b224e63SBarry Smith   } else {
15033b224e63SBarry Smith     pc->ops->apply = PCApply_FieldSplit;
15043b224e63SBarry Smith     pc->ops->view  = PCView_FieldSplit;
1505e69d4d44SBarry Smith     ierr = PetscObjectComposeFunctionDynamic((PetscObject)pc,"PCFieldSplitGetSubKSP_C","PCFieldSplitGetSubKSP_FieldSplit",PCFieldSplitGetSubKSP_FieldSplit);CHKERRQ(ierr);
15069e7d6b0aSBarry Smith     ierr = PetscObjectComposeFunctionDynamic((PetscObject)pc,"PCFieldSplitSchurPrecondition_C","",0);CHKERRQ(ierr);
1507c9c6ffaaSJed Brown     ierr = PetscObjectComposeFunctionDynamic((PetscObject)pc,"PCFieldSplitSetSchurFactType_C","",0);CHKERRQ(ierr);
15083b224e63SBarry Smith   }
150979416396SBarry Smith   PetscFunctionReturn(0);
151079416396SBarry Smith }
151179416396SBarry Smith EXTERN_C_END
151279416396SBarry Smith 
151351f519a2SBarry Smith EXTERN_C_BEGIN
151451f519a2SBarry Smith #undef __FUNCT__
151551f519a2SBarry Smith #define __FUNCT__ "PCFieldSplitSetBlockSize_FieldSplit"
15167087cfbeSBarry Smith PetscErrorCode  PCFieldSplitSetBlockSize_FieldSplit(PC pc,PetscInt bs)
151751f519a2SBarry Smith {
151851f519a2SBarry Smith   PC_FieldSplit  *jac = (PC_FieldSplit*)pc->data;
151951f519a2SBarry Smith 
152051f519a2SBarry Smith   PetscFunctionBegin;
152165e19b50SBarry Smith   if (bs < 1) SETERRQ1(((PetscObject)pc)->comm,PETSC_ERR_ARG_OUTOFRANGE,"Blocksize must be positive, you gave %D",bs);
152265e19b50SBarry Smith   if (jac->bs > 0 && jac->bs != bs) SETERRQ2(((PetscObject)pc)->comm,PETSC_ERR_ARG_WRONGSTATE,"Cannot change fieldsplit blocksize from %D to %D after it has been set",jac->bs,bs);
152351f519a2SBarry Smith   jac->bs = bs;
152451f519a2SBarry Smith   PetscFunctionReturn(0);
152551f519a2SBarry Smith }
152651f519a2SBarry Smith EXTERN_C_END
152751f519a2SBarry Smith 
152879416396SBarry Smith #undef __FUNCT__
152979416396SBarry Smith #define __FUNCT__ "PCFieldSplitSetType"
1530bc08b0f1SBarry Smith /*@
153179416396SBarry Smith    PCFieldSplitSetType - Sets the type of fieldsplit preconditioner.
153279416396SBarry Smith 
153379416396SBarry Smith    Collective on PC
153479416396SBarry Smith 
153579416396SBarry Smith    Input Parameter:
153679416396SBarry Smith .  pc - the preconditioner context
153781540f2fSBarry Smith .  type - PC_COMPOSITE_ADDITIVE, PC_COMPOSITE_MULTIPLICATIVE (default), PC_COMPOSITE_SYMMETRIC_MULTIPLICATIVE, PC_COMPOSITE_SPECIAL, PC_COMPOSITE_SCHUR
153879416396SBarry Smith 
153979416396SBarry Smith    Options Database Key:
1540a4efd8eaSMatthew Knepley .  -pc_fieldsplit_type <type: one of multiplicative, additive, symmetric_multiplicative, special, schur> - Sets fieldsplit preconditioner type
154179416396SBarry Smith 
1542b02e2d75SMatthew G Knepley    Level: Intermediate
154379416396SBarry Smith 
154479416396SBarry Smith .keywords: PC, set, type, composite preconditioner, additive, multiplicative
154579416396SBarry Smith 
154679416396SBarry Smith .seealso: PCCompositeSetType()
154779416396SBarry Smith 
154879416396SBarry Smith @*/
15497087cfbeSBarry Smith PetscErrorCode  PCFieldSplitSetType(PC pc,PCCompositeType type)
155079416396SBarry Smith {
15514ac538c5SBarry Smith   PetscErrorCode ierr;
155279416396SBarry Smith 
155379416396SBarry Smith   PetscFunctionBegin;
15540700a824SBarry Smith   PetscValidHeaderSpecific(pc,PC_CLASSID,1);
15554ac538c5SBarry Smith   ierr = PetscTryMethod(pc,"PCFieldSplitSetType_C",(PC,PCCompositeType),(pc,type));CHKERRQ(ierr);
155679416396SBarry Smith   PetscFunctionReturn(0);
155779416396SBarry Smith }
155879416396SBarry Smith 
1559b02e2d75SMatthew G Knepley #undef __FUNCT__
1560b02e2d75SMatthew G Knepley #define __FUNCT__ "PCFieldSplitGetType"
1561b02e2d75SMatthew G Knepley /*@
1562b02e2d75SMatthew G Knepley   PCFieldSplitGetType - Gets the type of fieldsplit preconditioner.
1563b02e2d75SMatthew G Knepley 
1564b02e2d75SMatthew G Knepley   Not collective
1565b02e2d75SMatthew G Knepley 
1566b02e2d75SMatthew G Knepley   Input Parameter:
1567b02e2d75SMatthew G Knepley . pc - the preconditioner context
1568b02e2d75SMatthew G Knepley 
1569b02e2d75SMatthew G Knepley   Output Parameter:
1570b02e2d75SMatthew G Knepley . type - PC_COMPOSITE_ADDITIVE, PC_COMPOSITE_MULTIPLICATIVE (default), PC_COMPOSITE_SYMMETRIC_MULTIPLICATIVE, PC_COMPOSITE_SPECIAL, PC_COMPOSITE_SCHUR
1571b02e2d75SMatthew G Knepley 
1572b02e2d75SMatthew G Knepley   Level: Intermediate
1573b02e2d75SMatthew G Knepley 
1574b02e2d75SMatthew G Knepley .keywords: PC, set, type, composite preconditioner, additive, multiplicative
1575b02e2d75SMatthew G Knepley .seealso: PCCompositeSetType()
1576b02e2d75SMatthew G Knepley @*/
1577b02e2d75SMatthew G Knepley PetscErrorCode PCFieldSplitGetType(PC pc, PCCompositeType *type)
1578b02e2d75SMatthew G Knepley {
1579b02e2d75SMatthew G Knepley   PC_FieldSplit *jac = (PC_FieldSplit *) pc->data;
1580b02e2d75SMatthew G Knepley 
1581b02e2d75SMatthew G Knepley   PetscFunctionBegin;
1582b02e2d75SMatthew G Knepley   PetscValidHeaderSpecific(pc,PC_CLASSID,1);
1583b02e2d75SMatthew G Knepley   PetscValidIntPointer(type,2);
1584b02e2d75SMatthew G Knepley   *type = jac->type;
1585b02e2d75SMatthew G Knepley   PetscFunctionReturn(0);
1586b02e2d75SMatthew G Knepley }
1587b02e2d75SMatthew G Knepley 
15880971522cSBarry Smith /* -------------------------------------------------------------------------------------*/
15890971522cSBarry Smith /*MC
1590a8c7a070SBarry Smith    PCFIELDSPLIT - Preconditioner created by combining separate preconditioners for individual
1591a04f6461SBarry Smith                   fields or groups of fields. See the users manual section "Solving Block Matrices" for more details.
15920971522cSBarry Smith 
1593edf189efSBarry Smith      To set options on the solvers for each block append -fieldsplit_ to all the PC
1594edf189efSBarry Smith         options database keys. For example, -fieldsplit_pc_type ilu -fieldsplit_pc_factor_levels 1
15950971522cSBarry Smith 
1596a8c7a070SBarry Smith      To set the options on the solvers separate for each block call PCFieldSplitGetSubKSP()
159769a612a9SBarry Smith          and set the options directly on the resulting KSP object
15980971522cSBarry Smith 
15990971522cSBarry Smith    Level: intermediate
16000971522cSBarry Smith 
160179416396SBarry Smith    Options Database Keys:
160281540f2fSBarry Smith +   -pc_fieldsplit_%d_fields <a,b,..> - indicates the fields to be used in the %d'th split
160381540f2fSBarry Smith .   -pc_fieldsplit_default - automatically add any fields to additional splits that have not
160481540f2fSBarry Smith                               been supplied explicitly by -pc_fieldsplit_%d_fields
160581540f2fSBarry Smith .   -pc_fieldsplit_block_size <bs> - size of block that defines fields (i.e. there are bs fields)
16060f188ba9SJed Brown .   -pc_fieldsplit_type <additive,multiplicative,symmetric_multiplicative,schur> - type of relaxation or factorization splitting
16070f188ba9SJed Brown .   -pc_fieldsplit_schur_precondition <self,user,diag> - default is diag
1608435f959eSBarry Smith .   -pc_fieldsplit_detect_saddle_point - automatically finds rows with zero or negative diagonal and uses Schur complement with no preconditioner as the solver
160979416396SBarry Smith 
16105d4c12cdSJungho Lee -    Options prefix for inner solvers when using Schur complement preconditioner are -fieldsplit_0_ and -fieldsplit_1_
16115d4c12cdSJungho Lee      for all other solvers they are -fieldsplit_%d_ for the dth field, use -fieldsplit_ for all fields
16125d4c12cdSJungho Lee 
1613c8a0d604SMatthew G Knepley    Notes:
1614c8a0d604SMatthew G Knepley     Use PCFieldSplitSetFields() to set fields defined by "strided" entries and PCFieldSplitSetIS()
1615d32f9abdSBarry Smith      to define a field by an arbitrary collection of entries.
1616d32f9abdSBarry Smith 
1617d32f9abdSBarry Smith       If no fields are set the default is used. The fields are defined by entries strided by bs,
1618d32f9abdSBarry Smith       beginning at 0 then 1, etc to bs-1. The block size can be set with PCFieldSplitSetBlockSize(),
1619d32f9abdSBarry Smith       if this is not called the block size defaults to the blocksize of the second matrix passed
1620d32f9abdSBarry Smith       to KSPSetOperators()/PCSetOperators().
1621d32f9abdSBarry Smith 
1622c8a0d604SMatthew G Knepley $     For the Schur complement preconditioner if J = ( A00 A01 )
1623c8a0d604SMatthew G Knepley $                                                    ( A10 A11 )
1624c8a0d604SMatthew G Knepley $     the preconditioner using full factorization is
1625c8a0d604SMatthew G Knepley $              ( I   -A10 ksp(A00) ) ( inv(A00)     0  ) (     I          0  )
1626c8a0d604SMatthew G Knepley $              ( 0         I       ) (   0      ksp(S) ) ( -A10 ksp(A00)  I  )
1627a04f6461SBarry Smith      where the action of inv(A00) is applied using the KSP solver with prefix -fieldsplit_0_. The action of
1628c8a0d604SMatthew G Knepley      ksp(S) is computed using the KSP solver with prefix -fieldsplit_splitname_ (where splitname was given
1629c8a0d604SMatthew G Knepley      in providing the SECOND split or 1 if not give). For PCFieldSplitGetKSP() when field number is 0,
1630c8a0d604SMatthew G Knepley      it returns the KSP associated with -fieldsplit_0_ while field number 1 gives -fieldsplit_1_ KSP. By default
1631a04f6461SBarry Smith      A11 is used to construct a preconditioner for S, use PCFieldSplitSchurPrecondition() to turn on or off this
1632c8a0d604SMatthew G Knepley      option. You can use the preconditioner PCLSC to precondition the Schur complement with -fieldsplit_1_pc_type lsc. The
1633c9c6ffaaSJed Brown      factorization type is set using -pc_fieldsplit_schur_fact_type <diag, lower, upper, full>. The full is shown above,
16345668aaf4SBarry Smith      diag gives
1635c8a0d604SMatthew G Knepley $              ( inv(A00)     0   )
1636c8a0d604SMatthew G Knepley $              (   0      -ksp(S) )
16375668aaf4SBarry Smith      note that slightly counter intuitively there is a negative in front of the ksp(S) so that the preconditioner is positive definite. The lower factorization is the inverse of
1638c8a0d604SMatthew G Knepley $              (  A00   0 )
1639c8a0d604SMatthew G Knepley $              (  A10   S )
1640c8a0d604SMatthew G Knepley      where the inverses of A00 and S are applied using KSPs. The upper factorization is the inverse of
1641c8a0d604SMatthew G Knepley $              ( A00 A01 )
1642c8a0d604SMatthew G Knepley $              (  0   S  )
1643c8a0d604SMatthew G Knepley      where again the inverses of A00 and S are applied using KSPs.
1644e69d4d44SBarry Smith 
1645edf189efSBarry Smith      If only one set of indices (one IS) is provided with PCFieldSplitSetIS() then the complement of that IS
1646edf189efSBarry Smith      is used automatically for a second block.
1647edf189efSBarry Smith 
1648ff218e97SBarry Smith      The fieldsplit preconditioner cannot currently be used with the BAIJ or SBAIJ data formats if the blocksize is larger than 1.
1649ff218e97SBarry Smith      Generally it should be used with the AIJ format.
1650ff218e97SBarry Smith 
1651ff218e97SBarry Smith      The forms of these preconditioners are closely related if not identical to forms derived as "Distributive Iterations", see,
1652ff218e97SBarry Smith      for example, page 294 in "Principles of Computational Fluid Dynamics" by Pieter Wesseling. Note that one can also use PCFIELDSPLIT
1653ff218e97SBarry Smith      inside a smoother resulting in "Distributive Smoothers".
16540716a85fSBarry Smith 
1655a541d17aSBarry Smith    Concepts: physics based preconditioners, block preconditioners
16560971522cSBarry Smith 
16577e8cb189SBarry Smith .seealso:  PCCreate(), PCSetType(), PCType (for list of available types), PC, Block_Preconditioners, PCLSC,
1658e69d4d44SBarry Smith            PCFieldSplitGetSubKSP(), PCFieldSplitSetFields(), PCFieldSplitSetType(), PCFieldSplitSetIS(), PCFieldSplitSchurPrecondition()
16590971522cSBarry Smith M*/
16600971522cSBarry Smith 
16610971522cSBarry Smith EXTERN_C_BEGIN
16620971522cSBarry Smith #undef __FUNCT__
16630971522cSBarry Smith #define __FUNCT__ "PCCreate_FieldSplit"
16647087cfbeSBarry Smith PetscErrorCode  PCCreate_FieldSplit(PC pc)
16650971522cSBarry Smith {
16660971522cSBarry Smith   PetscErrorCode ierr;
16670971522cSBarry Smith   PC_FieldSplit  *jac;
16680971522cSBarry Smith 
16690971522cSBarry Smith   PetscFunctionBegin;
167038f2d2fdSLisandro Dalcin   ierr = PetscNewLog(pc,PC_FieldSplit,&jac);CHKERRQ(ierr);
16710971522cSBarry Smith   jac->bs        = -1;
16720971522cSBarry Smith   jac->nsplits   = 0;
16733e197d65SBarry Smith   jac->type      = PC_COMPOSITE_MULTIPLICATIVE;
1674e6cab6aaSJed Brown   jac->schurpre  = PC_FIELDSPLIT_SCHUR_PRE_USER; /* Try user preconditioner first, fall back on diagonal */
1675c9c6ffaaSJed Brown   jac->schurfactorization = PC_FIELDSPLIT_SCHUR_FACT_FULL;
167651f519a2SBarry Smith 
16770971522cSBarry Smith   pc->data     = (void*)jac;
16780971522cSBarry Smith 
16790971522cSBarry Smith   pc->ops->apply             = PCApply_FieldSplit;
1680421e10b8SBarry Smith   pc->ops->applytranspose    = PCApplyTranspose_FieldSplit;
16810971522cSBarry Smith   pc->ops->setup             = PCSetUp_FieldSplit;
1682574deadeSBarry Smith   pc->ops->reset             = PCReset_FieldSplit;
16830971522cSBarry Smith   pc->ops->destroy           = PCDestroy_FieldSplit;
16840971522cSBarry Smith   pc->ops->setfromoptions    = PCSetFromOptions_FieldSplit;
16850971522cSBarry Smith   pc->ops->view              = PCView_FieldSplit;
16860971522cSBarry Smith   pc->ops->applyrichardson   = 0;
16870971522cSBarry Smith 
168869a612a9SBarry Smith   ierr = PetscObjectComposeFunctionDynamic((PetscObject)pc,"PCFieldSplitGetSubKSP_C","PCFieldSplitGetSubKSP_FieldSplit",
168969a612a9SBarry Smith                     PCFieldSplitGetSubKSP_FieldSplit);CHKERRQ(ierr);
16900971522cSBarry Smith   ierr = PetscObjectComposeFunctionDynamic((PetscObject)pc,"PCFieldSplitSetFields_C","PCFieldSplitSetFields_FieldSplit",
16910971522cSBarry Smith                     PCFieldSplitSetFields_FieldSplit);CHKERRQ(ierr);
1692704ba839SBarry Smith   ierr = PetscObjectComposeFunctionDynamic((PetscObject)pc,"PCFieldSplitSetIS_C","PCFieldSplitSetIS_FieldSplit",
1693704ba839SBarry Smith                     PCFieldSplitSetIS_FieldSplit);CHKERRQ(ierr);
169479416396SBarry Smith   ierr = PetscObjectComposeFunctionDynamic((PetscObject)pc,"PCFieldSplitSetType_C","PCFieldSplitSetType_FieldSplit",
169579416396SBarry Smith                     PCFieldSplitSetType_FieldSplit);CHKERRQ(ierr);
169651f519a2SBarry Smith   ierr = PetscObjectComposeFunctionDynamic((PetscObject)pc,"PCFieldSplitSetBlockSize_C","PCFieldSplitSetBlockSize_FieldSplit",
169751f519a2SBarry Smith                     PCFieldSplitSetBlockSize_FieldSplit);CHKERRQ(ierr);
16980971522cSBarry Smith   PetscFunctionReturn(0);
16990971522cSBarry Smith }
17000971522cSBarry Smith EXTERN_C_END
17010971522cSBarry Smith 
17020971522cSBarry Smith 
1703a541d17aSBarry Smith 
1704