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, >mp, 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(>mp);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