1dba47a55SKris Buschelman #define PETSCKSP_DLL 2dba47a55SKris Buschelman 30971522cSBarry Smith /* 40971522cSBarry Smith 50971522cSBarry Smith */ 66356e834SBarry Smith #include "private/pcimpl.h" /*I "petscpc.h" I*/ 70971522cSBarry Smith 8084e4875SJed Brown const char *PCFieldSplitSchurPreTypes[] = {"self","diag","user","PCFieldSplitSchurPreType","PC_FIELDSPLIT_SCHUR_PRE_",0}; 9084e4875SJed Brown 100971522cSBarry Smith typedef struct _PC_FieldSplitLink *PC_FieldSplitLink; 110971522cSBarry Smith struct _PC_FieldSplitLink { 1269a612a9SBarry Smith KSP ksp; 130971522cSBarry Smith Vec x,y; 140971522cSBarry Smith PetscInt nfields; 150971522cSBarry Smith PetscInt *fields; 161b9fc7fcSBarry Smith VecScatter sctx; 174aa3045dSJed Brown IS is; 1851f519a2SBarry Smith PC_FieldSplitLink next,previous; 190971522cSBarry Smith }; 200971522cSBarry Smith 210971522cSBarry Smith typedef struct { 2268dd23aaSBarry Smith PCCompositeType type; 23a4efd8eaSMatthew Knepley PetscTruth defaultsplit; /* Flag for a system with a set of 'k' scalar fields with the same layout (and bs = k) */ 24519d70e2SJed Brown PetscTruth 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 */ 31704ba839SBarry Smith PetscTruth 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 */ 3530ad9308SMatthew Knepley Mat schur; /* The Schur complement S = D - C A^{-1} B */ 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 */ 3830ad9308SMatthew Knepley KSP kspschur; /* The solver for S */ 3997bbdb24SBarry Smith PC_FieldSplitLink head; 400971522cSBarry Smith } PC_FieldSplit; 410971522cSBarry Smith 4216913363SBarry Smith /* 4316913363SBarry Smith Notes: there is no particular reason that pmat, x, and y are stored as arrays in PC_FieldSplit instead of 4416913363SBarry Smith inside PC_FieldSplitLink, just historical. If you want to be able to add new fields after already using the 4516913363SBarry Smith PC you could change this. 4616913363SBarry Smith */ 47084e4875SJed Brown 48e6cab6aaSJed Brown /* This helper is so that setting a user-provided preconditioning matrix is orthogonal to choosing to use it. This way the 49084e4875SJed Brown * application-provided FormJacobian can provide this matrix without interfering with the user's (command-line) choices. */ 50084e4875SJed Brown static Mat FieldSplitSchurPre(PC_FieldSplit *jac) 51084e4875SJed Brown { 52084e4875SJed Brown switch (jac->schurpre) { 53084e4875SJed Brown case PC_FIELDSPLIT_SCHUR_PRE_SELF: return jac->schur; 54084e4875SJed Brown case PC_FIELDSPLIT_SCHUR_PRE_DIAG: return jac->pmat[1]; 55084e4875SJed Brown case PC_FIELDSPLIT_SCHUR_PRE_USER: /* Use a user-provided matrix if it is given, otherwise diagonal block */ 56084e4875SJed Brown default: 57084e4875SJed Brown return jac->schur_user ? jac->schur_user : jac->pmat[1]; 58084e4875SJed Brown } 59084e4875SJed Brown } 60084e4875SJed Brown 61084e4875SJed Brown 620971522cSBarry Smith #undef __FUNCT__ 630971522cSBarry Smith #define __FUNCT__ "PCView_FieldSplit" 640971522cSBarry Smith static PetscErrorCode PCView_FieldSplit(PC pc,PetscViewer viewer) 650971522cSBarry Smith { 660971522cSBarry Smith PC_FieldSplit *jac = (PC_FieldSplit*)pc->data; 670971522cSBarry Smith PetscErrorCode ierr; 680971522cSBarry Smith PetscTruth iascii; 690971522cSBarry Smith PetscInt i,j; 705a9f2f41SSatish Balay PC_FieldSplitLink ilink = jac->head; 710971522cSBarry Smith 720971522cSBarry Smith PetscFunctionBegin; 730971522cSBarry Smith ierr = PetscTypeCompare((PetscObject)viewer,PETSC_VIEWER_ASCII,&iascii);CHKERRQ(ierr); 740971522cSBarry Smith if (iascii) { 7551f519a2SBarry Smith ierr = PetscViewerASCIIPrintf(viewer," FieldSplit with %s composition: total splits = %D, blocksize = %D\n",PCCompositeTypes[jac->type],jac->nsplits,jac->bs);CHKERRQ(ierr); 7669a612a9SBarry Smith ierr = PetscViewerASCIIPrintf(viewer," Solver info for each split is in the following KSP objects:\n");CHKERRQ(ierr); 770971522cSBarry Smith ierr = PetscViewerASCIIPushTab(viewer);CHKERRQ(ierr); 780971522cSBarry Smith for (i=0; i<jac->nsplits; i++) { 791ab39975SBarry Smith if (ilink->fields) { 800971522cSBarry Smith ierr = PetscViewerASCIIPrintf(viewer,"Split number %D Fields ",i);CHKERRQ(ierr); 8179416396SBarry Smith ierr = PetscViewerASCIIUseTabs(viewer,PETSC_FALSE);CHKERRQ(ierr); 825a9f2f41SSatish Balay for (j=0; j<ilink->nfields; j++) { 8379416396SBarry Smith if (j > 0) { 8479416396SBarry Smith ierr = PetscViewerASCIIPrintf(viewer,",");CHKERRQ(ierr); 8579416396SBarry Smith } 865a9f2f41SSatish Balay ierr = PetscViewerASCIIPrintf(viewer," %D",ilink->fields[j]);CHKERRQ(ierr); 870971522cSBarry Smith } 880971522cSBarry Smith ierr = PetscViewerASCIIPrintf(viewer,"\n");CHKERRQ(ierr); 8979416396SBarry Smith ierr = PetscViewerASCIIUseTabs(viewer,PETSC_TRUE);CHKERRQ(ierr); 901ab39975SBarry Smith } else { 911ab39975SBarry Smith ierr = PetscViewerASCIIPrintf(viewer,"Split number %D Defined by IS\n",i);CHKERRQ(ierr); 921ab39975SBarry Smith } 935a9f2f41SSatish Balay ierr = KSPView(ilink->ksp,viewer);CHKERRQ(ierr); 945a9f2f41SSatish Balay ilink = ilink->next; 950971522cSBarry Smith } 960971522cSBarry Smith ierr = PetscViewerASCIIPopTab(viewer);CHKERRQ(ierr); 970971522cSBarry Smith } else { 980971522cSBarry Smith SETERRQ1(PETSC_ERR_SUP,"Viewer type %s not supported for PCFieldSplit",((PetscObject)viewer)->type_name); 990971522cSBarry Smith } 1000971522cSBarry Smith PetscFunctionReturn(0); 1010971522cSBarry Smith } 1020971522cSBarry Smith 1030971522cSBarry Smith #undef __FUNCT__ 1043b224e63SBarry Smith #define __FUNCT__ "PCView_FieldSplit_Schur" 1053b224e63SBarry Smith static PetscErrorCode PCView_FieldSplit_Schur(PC pc,PetscViewer viewer) 1063b224e63SBarry Smith { 1073b224e63SBarry Smith PC_FieldSplit *jac = (PC_FieldSplit*)pc->data; 1083b224e63SBarry Smith PetscErrorCode ierr; 1093b224e63SBarry Smith PetscTruth iascii; 1103b224e63SBarry Smith PetscInt i,j; 1113b224e63SBarry Smith PC_FieldSplitLink ilink = jac->head; 1123b224e63SBarry Smith KSP ksp; 1133b224e63SBarry Smith 1143b224e63SBarry Smith PetscFunctionBegin; 1153b224e63SBarry Smith ierr = PetscTypeCompare((PetscObject)viewer,PETSC_VIEWER_ASCII,&iascii);CHKERRQ(ierr); 1163b224e63SBarry Smith if (iascii) { 1173b224e63SBarry Smith ierr = PetscViewerASCIIPrintf(viewer," FieldSplit with Schur preconditioner, blocksize = %D\n",jac->bs);CHKERRQ(ierr); 1183b224e63SBarry Smith ierr = PetscViewerASCIIPrintf(viewer," Split info:\n");CHKERRQ(ierr); 1193b224e63SBarry Smith ierr = PetscViewerASCIIPushTab(viewer);CHKERRQ(ierr); 1203b224e63SBarry Smith for (i=0; i<jac->nsplits; i++) { 1213b224e63SBarry Smith if (ilink->fields) { 1223b224e63SBarry Smith ierr = PetscViewerASCIIPrintf(viewer,"Split number %D Fields ",i);CHKERRQ(ierr); 1233b224e63SBarry Smith ierr = PetscViewerASCIIUseTabs(viewer,PETSC_FALSE);CHKERRQ(ierr); 1243b224e63SBarry Smith for (j=0; j<ilink->nfields; j++) { 1253b224e63SBarry Smith if (j > 0) { 1263b224e63SBarry Smith ierr = PetscViewerASCIIPrintf(viewer,",");CHKERRQ(ierr); 1273b224e63SBarry Smith } 1283b224e63SBarry Smith ierr = PetscViewerASCIIPrintf(viewer," %D",ilink->fields[j]);CHKERRQ(ierr); 1293b224e63SBarry Smith } 1303b224e63SBarry Smith ierr = PetscViewerASCIIPrintf(viewer,"\n");CHKERRQ(ierr); 1313b224e63SBarry Smith ierr = PetscViewerASCIIUseTabs(viewer,PETSC_TRUE);CHKERRQ(ierr); 1323b224e63SBarry Smith } else { 1333b224e63SBarry Smith ierr = PetscViewerASCIIPrintf(viewer,"Split number %D Defined by IS\n",i);CHKERRQ(ierr); 1343b224e63SBarry Smith } 1353b224e63SBarry Smith ilink = ilink->next; 1363b224e63SBarry Smith } 1373b224e63SBarry Smith ierr = PetscViewerASCIIPrintf(viewer,"KSP solver for A block \n");CHKERRQ(ierr); 1383b224e63SBarry Smith ierr = MatSchurComplementGetKSP(jac->schur,&ksp);CHKERRQ(ierr); 1393b224e63SBarry Smith ierr = PetscViewerASCIIPushTab(viewer);CHKERRQ(ierr); 1403b224e63SBarry Smith ierr = KSPView(ksp,viewer);CHKERRQ(ierr); 1413b224e63SBarry Smith ierr = PetscViewerASCIIPopTab(viewer);CHKERRQ(ierr); 1423b224e63SBarry Smith ierr = PetscViewerASCIIPrintf(viewer,"KSP solver for S = D - C inv(A) B \n");CHKERRQ(ierr); 1433b224e63SBarry Smith ierr = PetscViewerASCIIPushTab(viewer);CHKERRQ(ierr); 1443b224e63SBarry Smith ierr = KSPView(jac->kspschur,viewer);CHKERRQ(ierr); 1453b224e63SBarry Smith ierr = PetscViewerASCIIPopTab(viewer);CHKERRQ(ierr); 1463b224e63SBarry Smith ierr = PetscViewerASCIIPopTab(viewer);CHKERRQ(ierr); 1473b224e63SBarry Smith } else { 1483b224e63SBarry Smith SETERRQ1(PETSC_ERR_SUP,"Viewer type %s not supported for PCFieldSplit",((PetscObject)viewer)->type_name); 1493b224e63SBarry Smith } 1503b224e63SBarry Smith PetscFunctionReturn(0); 1513b224e63SBarry Smith } 1523b224e63SBarry Smith 1533b224e63SBarry Smith #undef __FUNCT__ 15469a612a9SBarry Smith #define __FUNCT__ "PCFieldSplitSetDefaults" 15569a612a9SBarry Smith static PetscErrorCode PCFieldSplitSetDefaults(PC pc) 1560971522cSBarry Smith { 1570971522cSBarry Smith PC_FieldSplit *jac = (PC_FieldSplit*)pc->data; 1580971522cSBarry Smith PetscErrorCode ierr; 1595a9f2f41SSatish Balay PC_FieldSplitLink ilink = jac->head; 160d32f9abdSBarry Smith PetscInt i = 0,*ifields,nfields; 161d32f9abdSBarry Smith PetscTruth flg = PETSC_FALSE,*fields,flg2; 162d32f9abdSBarry Smith char optionname[128]; 1630971522cSBarry Smith 1640971522cSBarry Smith PetscFunctionBegin; 165d32f9abdSBarry Smith if (!ilink) { 166d32f9abdSBarry Smith 167521d7252SBarry Smith if (jac->bs <= 0) { 168704ba839SBarry Smith if (pc->pmat) { 169521d7252SBarry Smith ierr = MatGetBlockSize(pc->pmat,&jac->bs);CHKERRQ(ierr); 170704ba839SBarry Smith } else { 171704ba839SBarry Smith jac->bs = 1; 172704ba839SBarry Smith } 173521d7252SBarry Smith } 174d32f9abdSBarry Smith 175d32f9abdSBarry Smith ierr = PetscOptionsGetTruth(((PetscObject)pc)->prefix,"-pc_fieldsplit_default",&flg,PETSC_NULL);CHKERRQ(ierr); 176d32f9abdSBarry Smith if (!flg) { 177d32f9abdSBarry Smith /* Allow user to set fields from command line, if bs was known at the time of PCSetFromOptions_FieldSplit() 178d32f9abdSBarry Smith then it is set there. This is not ideal because we should only have options set in XXSetFromOptions(). */ 179d32f9abdSBarry Smith flg = PETSC_TRUE; /* switched off automatically if user sets fields manually here */ 180d32f9abdSBarry Smith ierr = PetscMalloc(jac->bs*sizeof(PetscInt),&ifields);CHKERRQ(ierr); 181d32f9abdSBarry Smith while (PETSC_TRUE) { 182d32f9abdSBarry Smith sprintf(optionname,"-pc_fieldsplit_%d_fields",(int)i++); 183d32f9abdSBarry Smith nfields = jac->bs; 184d32f9abdSBarry Smith ierr = PetscOptionsGetIntArray(((PetscObject)pc)->prefix,optionname,ifields,&nfields,&flg2);CHKERRQ(ierr); 185d32f9abdSBarry Smith if (!flg2) break; 186d32f9abdSBarry Smith if (!nfields) SETERRQ(PETSC_ERR_USER,"Cannot list zero fields"); 187d32f9abdSBarry Smith flg = PETSC_FALSE; 188d32f9abdSBarry Smith ierr = PCFieldSplitSetFields(pc,nfields,ifields);CHKERRQ(ierr); 189d32f9abdSBarry Smith } 190d32f9abdSBarry Smith ierr = PetscFree(ifields);CHKERRQ(ierr); 191d32f9abdSBarry Smith } 192d32f9abdSBarry Smith 193d32f9abdSBarry Smith if (flg) { 194d32f9abdSBarry Smith ierr = PetscInfo(pc,"Using default splitting of fields\n");CHKERRQ(ierr); 19579416396SBarry Smith ierr = PetscMalloc(jac->bs*sizeof(PetscTruth),&fields);CHKERRQ(ierr); 19679416396SBarry Smith ierr = PetscMemzero(fields,jac->bs*sizeof(PetscTruth));CHKERRQ(ierr); 1975a9f2f41SSatish Balay while (ilink) { 1985a9f2f41SSatish Balay for (i=0; i<ilink->nfields; i++) { 1995a9f2f41SSatish Balay fields[ilink->fields[i]] = PETSC_TRUE; 200521d7252SBarry Smith } 2015a9f2f41SSatish Balay ilink = ilink->next; 20279416396SBarry Smith } 20397bbdb24SBarry Smith jac->defaultsplit = PETSC_TRUE; 20479416396SBarry Smith for (i=0; i<jac->bs; i++) { 20579416396SBarry Smith if (!fields[i]) { 20679416396SBarry Smith ierr = PCFieldSplitSetFields(pc,1,&i);CHKERRQ(ierr); 20779416396SBarry Smith } else { 20879416396SBarry Smith jac->defaultsplit = PETSC_FALSE; 20979416396SBarry Smith } 21079416396SBarry Smith } 21168dd23aaSBarry Smith ierr = PetscFree(fields);CHKERRQ(ierr); 212521d7252SBarry Smith } 213edf189efSBarry Smith } else if (jac->nsplits == 1) { 214edf189efSBarry Smith if (ilink->is) { 215edf189efSBarry Smith IS is2; 216edf189efSBarry Smith PetscInt nmin,nmax; 217edf189efSBarry Smith 218edf189efSBarry Smith ierr = MatGetOwnershipRange(pc->mat,&nmin,&nmax);CHKERRQ(ierr); 219edf189efSBarry Smith ierr = ISComplement(ilink->is,nmin,nmax,&is2);CHKERRQ(ierr); 220edf189efSBarry Smith ierr = PCFieldSplitSetIS(pc,is2);CHKERRQ(ierr); 221edf189efSBarry Smith ierr = ISDestroy(is2);CHKERRQ(ierr); 222edf189efSBarry Smith } else { 223edf189efSBarry Smith SETERRQ(PETSC_ERR_SUP,"Must provide at least two sets of fields to PCFieldSplit()"); 224edf189efSBarry Smith } 225d32f9abdSBarry Smith } 22669a612a9SBarry Smith PetscFunctionReturn(0); 22769a612a9SBarry Smith } 22869a612a9SBarry Smith 22969a612a9SBarry Smith 23069a612a9SBarry Smith #undef __FUNCT__ 23169a612a9SBarry Smith #define __FUNCT__ "PCSetUp_FieldSplit" 23269a612a9SBarry Smith static PetscErrorCode PCSetUp_FieldSplit(PC pc) 23369a612a9SBarry Smith { 23469a612a9SBarry Smith PC_FieldSplit *jac = (PC_FieldSplit*)pc->data; 23569a612a9SBarry Smith PetscErrorCode ierr; 2365a9f2f41SSatish Balay PC_FieldSplitLink ilink; 237cf502942SBarry Smith PetscInt i,nsplit,ccsize; 23869a612a9SBarry Smith MatStructure flag = pc->flag; 23968dd23aaSBarry Smith PetscTruth sorted,getsub; 24069a612a9SBarry Smith 24169a612a9SBarry Smith PetscFunctionBegin; 24269a612a9SBarry Smith ierr = PCFieldSplitSetDefaults(pc);CHKERRQ(ierr); 24397bbdb24SBarry Smith nsplit = jac->nsplits; 2445a9f2f41SSatish Balay ilink = jac->head; 24597bbdb24SBarry Smith 24697bbdb24SBarry Smith /* get the matrices for each split */ 247704ba839SBarry Smith if (!jac->issetup) { 2481b9fc7fcSBarry Smith PetscInt rstart,rend,nslots,bs; 24997bbdb24SBarry Smith 250704ba839SBarry Smith jac->issetup = PETSC_TRUE; 251704ba839SBarry Smith 252704ba839SBarry Smith /* This is done here instead of in PCFieldSplitSetFields() because may not have matrix at that point */ 25351f519a2SBarry Smith bs = jac->bs; 25497bbdb24SBarry Smith ierr = MatGetOwnershipRange(pc->pmat,&rstart,&rend);CHKERRQ(ierr); 255cf502942SBarry Smith ierr = MatGetLocalSize(pc->pmat,PETSC_NULL,&ccsize);CHKERRQ(ierr); 2561b9fc7fcSBarry Smith nslots = (rend - rstart)/bs; 2571b9fc7fcSBarry Smith for (i=0; i<nsplit; i++) { 2581b9fc7fcSBarry Smith if (jac->defaultsplit) { 259704ba839SBarry Smith ierr = ISCreateStride(((PetscObject)pc)->comm,nslots,rstart+i,nsplit,&ilink->is);CHKERRQ(ierr); 260704ba839SBarry Smith } else if (!ilink->is) { 261ccb205f8SBarry Smith if (ilink->nfields > 1) { 2625a9f2f41SSatish Balay PetscInt *ii,j,k,nfields = ilink->nfields,*fields = ilink->fields; 2635a9f2f41SSatish Balay ierr = PetscMalloc(ilink->nfields*nslots*sizeof(PetscInt),&ii);CHKERRQ(ierr); 2641b9fc7fcSBarry Smith for (j=0; j<nslots; j++) { 2651b9fc7fcSBarry Smith for (k=0; k<nfields; k++) { 2661b9fc7fcSBarry Smith ii[nfields*j + k] = rstart + bs*j + fields[k]; 26797bbdb24SBarry Smith } 26897bbdb24SBarry Smith } 269704ba839SBarry Smith ierr = ISCreateGeneral(((PetscObject)pc)->comm,nslots*nfields,ii,&ilink->is);CHKERRQ(ierr); 270ccb205f8SBarry Smith ierr = PetscFree(ii);CHKERRQ(ierr); 271ccb205f8SBarry Smith } else { 272704ba839SBarry Smith ierr = ISCreateStride(((PetscObject)pc)->comm,nslots,rstart+ilink->fields[0],bs,&ilink->is);CHKERRQ(ierr); 273ccb205f8SBarry Smith } 2743e197d65SBarry Smith } 275704ba839SBarry Smith ierr = ISSorted(ilink->is,&sorted);CHKERRQ(ierr); 2761b9fc7fcSBarry Smith if (!sorted) SETERRQ(PETSC_ERR_USER,"Fields must be sorted when creating split"); 277704ba839SBarry Smith ilink = ilink->next; 2781b9fc7fcSBarry Smith } 2791b9fc7fcSBarry Smith } 2801b9fc7fcSBarry Smith 281704ba839SBarry Smith ilink = jac->head; 28297bbdb24SBarry Smith if (!jac->pmat) { 283cf502942SBarry Smith ierr = PetscMalloc(nsplit*sizeof(Mat),&jac->pmat);CHKERRQ(ierr); 284cf502942SBarry Smith for (i=0; i<nsplit; i++) { 2854aa3045dSJed Brown ierr = MatGetSubMatrix(pc->pmat,ilink->is,ilink->is,MAT_INITIAL_MATRIX,&jac->pmat[i]);CHKERRQ(ierr); 286704ba839SBarry Smith ilink = ilink->next; 287cf502942SBarry Smith } 28897bbdb24SBarry Smith } else { 289cf502942SBarry Smith for (i=0; i<nsplit; i++) { 2904aa3045dSJed Brown ierr = MatGetSubMatrix(pc->pmat,ilink->is,ilink->is,MAT_REUSE_MATRIX,&jac->pmat[i]);CHKERRQ(ierr); 291704ba839SBarry Smith ilink = ilink->next; 292cf502942SBarry Smith } 29397bbdb24SBarry Smith } 294519d70e2SJed Brown if (jac->realdiagonal) { 295519d70e2SJed Brown ilink = jac->head; 296519d70e2SJed Brown if (!jac->mat) { 297519d70e2SJed Brown ierr = PetscMalloc(nsplit*sizeof(Mat),&jac->mat);CHKERRQ(ierr); 298519d70e2SJed Brown for (i=0; i<nsplit; i++) { 299519d70e2SJed Brown ierr = MatGetSubMatrix(pc->mat,ilink->is,ilink->is,MAT_INITIAL_MATRIX,&jac->mat[i]);CHKERRQ(ierr); 300519d70e2SJed Brown ilink = ilink->next; 301519d70e2SJed Brown } 302519d70e2SJed Brown } else { 303519d70e2SJed Brown for (i=0; i<nsplit; i++) { 304519d70e2SJed Brown ierr = MatGetSubMatrix(pc->mat,ilink->is,ilink->is,MAT_REUSE_MATRIX,&jac->mat[i]);CHKERRQ(ierr); 305519d70e2SJed Brown ilink = ilink->next; 306519d70e2SJed Brown } 307519d70e2SJed Brown } 308519d70e2SJed Brown } else { 309519d70e2SJed Brown jac->mat = jac->pmat; 310519d70e2SJed Brown } 31197bbdb24SBarry Smith 312e6cab6aaSJed Brown if (jac->type != PC_COMPOSITE_SCHUR) { 31368dd23aaSBarry Smith /* extract the rows of the matrix associated with each field: used for efficient computation of residual inside algorithm */ 31468dd23aaSBarry Smith ierr = MatHasOperation(pc->mat,MATOP_GET_SUBMATRIX,&getsub);CHKERRQ(ierr); 3153b224e63SBarry Smith if (getsub && jac->type != PC_COMPOSITE_ADDITIVE && jac->type != PC_COMPOSITE_SCHUR) { 31668dd23aaSBarry Smith ilink = jac->head; 31768dd23aaSBarry Smith if (!jac->Afield) { 31868dd23aaSBarry Smith ierr = PetscMalloc(nsplit*sizeof(Mat),&jac->Afield);CHKERRQ(ierr); 31968dd23aaSBarry Smith for (i=0; i<nsplit; i++) { 3204aa3045dSJed Brown ierr = MatGetSubMatrix(pc->mat,ilink->is,PETSC_NULL,MAT_INITIAL_MATRIX,&jac->Afield[i]);CHKERRQ(ierr); 32168dd23aaSBarry Smith ilink = ilink->next; 32268dd23aaSBarry Smith } 32368dd23aaSBarry Smith } else { 32468dd23aaSBarry Smith for (i=0; i<nsplit; i++) { 3254aa3045dSJed Brown ierr = MatGetSubMatrix(pc->mat,ilink->is,PETSC_NULL,MAT_REUSE_MATRIX,&jac->Afield[i]);CHKERRQ(ierr); 32668dd23aaSBarry Smith ilink = ilink->next; 32768dd23aaSBarry Smith } 32868dd23aaSBarry Smith } 32968dd23aaSBarry Smith } 330e6cab6aaSJed Brown } 33168dd23aaSBarry Smith 3323b224e63SBarry Smith if (jac->type == PC_COMPOSITE_SCHUR) { 3333b224e63SBarry Smith IS ccis; 3344aa3045dSJed Brown PetscInt rstart,rend; 3353b224e63SBarry Smith if (nsplit != 2) SETERRQ(PETSC_ERR_ARG_INCOMP,"To use Schur complement preconditioner you must have exactly 2 fields"); 33668dd23aaSBarry Smith 337e6cab6aaSJed Brown /* When extracting off-diagonal submatrices, we take complements from this range */ 338e6cab6aaSJed Brown ierr = MatGetOwnershipRangeColumn(pc->mat,&rstart,&rend);CHKERRQ(ierr); 339e6cab6aaSJed Brown 3403b224e63SBarry Smith /* need to handle case when one is resetting up the preconditioner */ 3413b224e63SBarry Smith if (jac->schur) { 3423b224e63SBarry Smith ilink = jac->head; 3434aa3045dSJed Brown ierr = ISComplement(ilink->is,rstart,rend,&ccis);CHKERRQ(ierr); 3444aa3045dSJed Brown ierr = MatGetSubMatrix(pc->mat,ilink->is,ccis,MAT_REUSE_MATRIX,&jac->B);CHKERRQ(ierr); 3453b224e63SBarry Smith ierr = ISDestroy(ccis);CHKERRQ(ierr); 3463b224e63SBarry Smith ilink = ilink->next; 3474aa3045dSJed Brown ierr = ISComplement(ilink->is,rstart,rend,&ccis);CHKERRQ(ierr); 3484aa3045dSJed Brown ierr = MatGetSubMatrix(pc->mat,ilink->is,ccis,MAT_REUSE_MATRIX,&jac->C);CHKERRQ(ierr); 3493b224e63SBarry Smith ierr = ISDestroy(ccis);CHKERRQ(ierr); 350519d70e2SJed Brown ierr = MatSchurComplementUpdate(jac->schur,jac->mat[0],jac->pmat[0],jac->B,jac->C,jac->pmat[1],pc->flag);CHKERRQ(ierr); 351084e4875SJed Brown ierr = KSPSetOperators(jac->kspschur,jac->schur,FieldSplitSchurPre(jac),pc->flag);CHKERRQ(ierr); 3523b224e63SBarry Smith 3533b224e63SBarry Smith } else { 3541cee3971SBarry Smith KSP ksp; 3553b224e63SBarry Smith 3563b224e63SBarry Smith /* extract the B and C matrices */ 3573b224e63SBarry Smith ilink = jac->head; 3584aa3045dSJed Brown ierr = ISComplement(ilink->is,rstart,rend,&ccis);CHKERRQ(ierr); 3594aa3045dSJed Brown ierr = MatGetSubMatrix(pc->mat,ilink->is,ccis,MAT_INITIAL_MATRIX,&jac->B);CHKERRQ(ierr); 3603b224e63SBarry Smith ierr = ISDestroy(ccis);CHKERRQ(ierr); 3613b224e63SBarry Smith ilink = ilink->next; 3624aa3045dSJed Brown ierr = ISComplement(ilink->is,rstart,rend,&ccis);CHKERRQ(ierr); 3634aa3045dSJed Brown ierr = MatGetSubMatrix(pc->mat,ilink->is,ccis,MAT_INITIAL_MATRIX,&jac->C);CHKERRQ(ierr); 3643b224e63SBarry Smith ierr = ISDestroy(ccis);CHKERRQ(ierr); 365084e4875SJed Brown /* Better would be to use 'mat[0]' (diagonal block of the real matrix) preconditioned by pmat[0] */ 366519d70e2SJed Brown ierr = MatCreateSchurComplement(jac->mat[0],jac->pmat[0],jac->B,jac->C,jac->mat[1],&jac->schur);CHKERRQ(ierr); 3671cee3971SBarry Smith ierr = MatSchurComplementGetKSP(jac->schur,&ksp);CHKERRQ(ierr); 368e69d4d44SBarry Smith ierr = PetscObjectIncrementTabLevel((PetscObject)ksp,(PetscObject)pc,2);CHKERRQ(ierr); 3693b224e63SBarry Smith ierr = MatSetFromOptions(jac->schur);CHKERRQ(ierr); 3703b224e63SBarry Smith 3713b224e63SBarry Smith ierr = KSPCreate(((PetscObject)pc)->comm,&jac->kspschur);CHKERRQ(ierr); 3721cee3971SBarry Smith ierr = PetscObjectIncrementTabLevel((PetscObject)jac->kspschur,(PetscObject)pc,1);CHKERRQ(ierr); 373084e4875SJed Brown ierr = KSPSetOperators(jac->kspschur,jac->schur,FieldSplitSchurPre(jac),DIFFERENT_NONZERO_PATTERN);CHKERRQ(ierr); 374084e4875SJed Brown if (jac->schurpre == PC_FIELDSPLIT_SCHUR_PRE_SELF) { 375084e4875SJed Brown PC pc; 376084e4875SJed Brown ierr = KSPGetPC(ksp,&pc);CHKERRQ(ierr); 377084e4875SJed Brown ierr = PCSetType(pc,PCNONE);CHKERRQ(ierr); 378084e4875SJed Brown /* Note: This is bad if there exist preconditioners for MATSCHURCOMPLEMENT */ 379e69d4d44SBarry Smith } 3803b224e63SBarry Smith ierr = KSPSetOptionsPrefix(jac->kspschur,((PetscObject)pc)->prefix);CHKERRQ(ierr); 381edf189efSBarry Smith ierr = KSPAppendOptionsPrefix(jac->kspschur,"fieldsplit_1_");CHKERRQ(ierr); 3823b224e63SBarry Smith /* really want setfromoptions called in PCSetFromOptions_FieldSplit(), but it is not ready yet */ 3833b224e63SBarry Smith ierr = KSPSetFromOptions(jac->kspschur);CHKERRQ(ierr); 3843b224e63SBarry Smith 3853b224e63SBarry Smith ierr = PetscMalloc2(2,Vec,&jac->x,2,Vec,&jac->y);CHKERRQ(ierr); 3863b224e63SBarry Smith ierr = MatGetVecs(jac->pmat[0],&jac->x[0],&jac->y[0]);CHKERRQ(ierr); 3873b224e63SBarry Smith ierr = MatGetVecs(jac->pmat[1],&jac->x[1],&jac->y[1]);CHKERRQ(ierr); 3883b224e63SBarry Smith ilink = jac->head; 3893b224e63SBarry Smith ilink->x = jac->x[0]; ilink->y = jac->y[0]; 3903b224e63SBarry Smith ilink = ilink->next; 3913b224e63SBarry Smith ilink->x = jac->x[1]; ilink->y = jac->y[1]; 3923b224e63SBarry Smith } 3933b224e63SBarry Smith } else { 39497bbdb24SBarry Smith /* set up the individual PCs */ 39597bbdb24SBarry Smith i = 0; 3965a9f2f41SSatish Balay ilink = jac->head; 3975a9f2f41SSatish Balay while (ilink) { 398519d70e2SJed Brown ierr = KSPSetOperators(ilink->ksp,jac->mat[i],jac->pmat[i],flag);CHKERRQ(ierr); 3993b224e63SBarry Smith /* really want setfromoptions called in PCSetFromOptions_FieldSplit(), but it is not ready yet */ 4005a9f2f41SSatish Balay ierr = KSPSetFromOptions(ilink->ksp);CHKERRQ(ierr); 4015a9f2f41SSatish Balay ierr = KSPSetUp(ilink->ksp);CHKERRQ(ierr); 40297bbdb24SBarry Smith i++; 4035a9f2f41SSatish Balay ilink = ilink->next; 4040971522cSBarry Smith } 40597bbdb24SBarry Smith 40697bbdb24SBarry Smith /* create work vectors for each split */ 4071b9fc7fcSBarry Smith if (!jac->x) { 40897bbdb24SBarry Smith ierr = PetscMalloc2(nsplit,Vec,&jac->x,nsplit,Vec,&jac->y);CHKERRQ(ierr); 4095a9f2f41SSatish Balay ilink = jac->head; 41097bbdb24SBarry Smith for (i=0; i<nsplit; i++) { 411906ed7ccSBarry Smith Vec *vl,*vr; 412906ed7ccSBarry Smith 413906ed7ccSBarry Smith ierr = KSPGetVecs(ilink->ksp,1,&vr,1,&vl);CHKERRQ(ierr); 414906ed7ccSBarry Smith ilink->x = *vr; 415906ed7ccSBarry Smith ilink->y = *vl; 416906ed7ccSBarry Smith ierr = PetscFree(vr);CHKERRQ(ierr); 417906ed7ccSBarry Smith ierr = PetscFree(vl);CHKERRQ(ierr); 4185a9f2f41SSatish Balay jac->x[i] = ilink->x; 4195a9f2f41SSatish Balay jac->y[i] = ilink->y; 4205a9f2f41SSatish Balay ilink = ilink->next; 42197bbdb24SBarry Smith } 4223b224e63SBarry Smith } 4233b224e63SBarry Smith } 4243b224e63SBarry Smith 4253b224e63SBarry Smith 426d0f46423SBarry Smith if (!jac->head->sctx) { 4273b224e63SBarry Smith Vec xtmp; 4283b224e63SBarry Smith 42979416396SBarry Smith /* compute scatter contexts needed by multiplicative versions and non-default splits */ 4301b9fc7fcSBarry Smith 4315a9f2f41SSatish Balay ilink = jac->head; 4321b9fc7fcSBarry Smith ierr = MatGetVecs(pc->pmat,&xtmp,PETSC_NULL);CHKERRQ(ierr); 4331b9fc7fcSBarry Smith for (i=0; i<nsplit; i++) { 434704ba839SBarry Smith ierr = VecScatterCreate(xtmp,ilink->is,jac->x[i],PETSC_NULL,&ilink->sctx);CHKERRQ(ierr); 4355a9f2f41SSatish Balay ilink = ilink->next; 4361b9fc7fcSBarry Smith } 4371b9fc7fcSBarry Smith ierr = VecDestroy(xtmp);CHKERRQ(ierr); 4381b9fc7fcSBarry Smith } 4390971522cSBarry Smith PetscFunctionReturn(0); 4400971522cSBarry Smith } 4410971522cSBarry Smith 4425a9f2f41SSatish Balay #define FieldSplitSplitSolveAdd(ilink,xx,yy) \ 443ca9f406cSSatish Balay (VecScatterBegin(ilink->sctx,xx,ilink->x,INSERT_VALUES,SCATTER_FORWARD) || \ 444ca9f406cSSatish Balay VecScatterEnd(ilink->sctx,xx,ilink->x,INSERT_VALUES,SCATTER_FORWARD) || \ 4455a9f2f41SSatish Balay KSPSolve(ilink->ksp,ilink->x,ilink->y) || \ 446ca9f406cSSatish Balay VecScatterBegin(ilink->sctx,ilink->y,yy,ADD_VALUES,SCATTER_REVERSE) || \ 447ca9f406cSSatish Balay VecScatterEnd(ilink->sctx,ilink->y,yy,ADD_VALUES,SCATTER_REVERSE)) 44879416396SBarry Smith 4490971522cSBarry Smith #undef __FUNCT__ 4503b224e63SBarry Smith #define __FUNCT__ "PCApply_FieldSplit_Schur" 4513b224e63SBarry Smith static PetscErrorCode PCApply_FieldSplit_Schur(PC pc,Vec x,Vec y) 4523b224e63SBarry Smith { 4533b224e63SBarry Smith PC_FieldSplit *jac = (PC_FieldSplit*)pc->data; 4543b224e63SBarry Smith PetscErrorCode ierr; 4553b224e63SBarry Smith KSP ksp; 4563b224e63SBarry Smith PC_FieldSplitLink ilinkA = jac->head, ilinkD = ilinkA->next; 4573b224e63SBarry Smith 4583b224e63SBarry Smith PetscFunctionBegin; 4593b224e63SBarry Smith ierr = MatSchurComplementGetKSP(jac->schur,&ksp);CHKERRQ(ierr); 4603b224e63SBarry Smith 4613b224e63SBarry Smith ierr = VecScatterBegin(ilinkA->sctx,x,ilinkA->x,INSERT_VALUES,SCATTER_FORWARD);CHKERRQ(ierr); 4623b224e63SBarry Smith ierr = VecScatterEnd(ilinkA->sctx,x,ilinkA->x,INSERT_VALUES,SCATTER_FORWARD);CHKERRQ(ierr); 4633b224e63SBarry Smith ierr = KSPSolve(ksp,ilinkA->x,ilinkA->y);CHKERRQ(ierr); 4643b224e63SBarry Smith ierr = MatMult(jac->C,ilinkA->y,ilinkD->x);CHKERRQ(ierr); 4653b224e63SBarry Smith ierr = VecScale(ilinkD->x,-1.0);CHKERRQ(ierr); 4663b224e63SBarry Smith ierr = VecScatterBegin(ilinkD->sctx,x,ilinkD->x,ADD_VALUES,SCATTER_FORWARD);CHKERRQ(ierr); 4673b224e63SBarry Smith ierr = VecScatterEnd(ilinkD->sctx,x,ilinkD->x,ADD_VALUES,SCATTER_FORWARD);CHKERRQ(ierr); 4683b224e63SBarry Smith 4693b224e63SBarry Smith ierr = KSPSolve(jac->kspschur,ilinkD->x,ilinkD->y);CHKERRQ(ierr); 4703b224e63SBarry Smith ierr = VecScatterBegin(ilinkD->sctx,ilinkD->y,y,INSERT_VALUES,SCATTER_REVERSE);CHKERRQ(ierr); 4713b224e63SBarry Smith ierr = VecScatterEnd(ilinkD->sctx,ilinkD->y,y,INSERT_VALUES,SCATTER_REVERSE);CHKERRQ(ierr); 4723b224e63SBarry Smith 4733b224e63SBarry Smith ierr = MatMult(jac->B,ilinkD->y,ilinkA->y);CHKERRQ(ierr); 4743b224e63SBarry Smith ierr = VecAXPY(ilinkA->x,-1.0,ilinkA->y);CHKERRQ(ierr); 4753b224e63SBarry Smith ierr = KSPSolve(ksp,ilinkA->x,ilinkA->y);CHKERRQ(ierr); 4763b224e63SBarry Smith ierr = VecScatterBegin(ilinkA->sctx,ilinkA->y,y,INSERT_VALUES,SCATTER_REVERSE);CHKERRQ(ierr); 4773b224e63SBarry Smith ierr = VecScatterEnd(ilinkA->sctx,ilinkA->y,y,INSERT_VALUES,SCATTER_REVERSE);CHKERRQ(ierr); 4783b224e63SBarry Smith 4793b224e63SBarry Smith PetscFunctionReturn(0); 4803b224e63SBarry Smith } 4813b224e63SBarry Smith 4823b224e63SBarry Smith #undef __FUNCT__ 4830971522cSBarry Smith #define __FUNCT__ "PCApply_FieldSplit" 4840971522cSBarry Smith static PetscErrorCode PCApply_FieldSplit(PC pc,Vec x,Vec y) 4850971522cSBarry Smith { 4860971522cSBarry Smith PC_FieldSplit *jac = (PC_FieldSplit*)pc->data; 4870971522cSBarry Smith PetscErrorCode ierr; 4885a9f2f41SSatish Balay PC_FieldSplitLink ilink = jac->head; 489*af93645bSJed Brown PetscInt cnt; 4900971522cSBarry Smith 4910971522cSBarry Smith PetscFunctionBegin; 49251f519a2SBarry Smith CHKMEMQ; 49351f519a2SBarry Smith ierr = VecSetBlockSize(x,jac->bs);CHKERRQ(ierr); 49451f519a2SBarry Smith ierr = VecSetBlockSize(y,jac->bs);CHKERRQ(ierr); 49551f519a2SBarry Smith 49679416396SBarry Smith if (jac->type == PC_COMPOSITE_ADDITIVE) { 4971b9fc7fcSBarry Smith if (jac->defaultsplit) { 4980971522cSBarry Smith ierr = VecStrideGatherAll(x,jac->x,INSERT_VALUES);CHKERRQ(ierr); 4995a9f2f41SSatish Balay while (ilink) { 5005a9f2f41SSatish Balay ierr = KSPSolve(ilink->ksp,ilink->x,ilink->y);CHKERRQ(ierr); 5015a9f2f41SSatish Balay ilink = ilink->next; 5020971522cSBarry Smith } 5030971522cSBarry Smith ierr = VecStrideScatterAll(jac->y,y,INSERT_VALUES);CHKERRQ(ierr); 5041b9fc7fcSBarry Smith } else { 505efb30889SBarry Smith ierr = VecSet(y,0.0);CHKERRQ(ierr); 5065a9f2f41SSatish Balay while (ilink) { 5075a9f2f41SSatish Balay ierr = FieldSplitSplitSolveAdd(ilink,x,y);CHKERRQ(ierr); 5085a9f2f41SSatish Balay ilink = ilink->next; 5091b9fc7fcSBarry Smith } 5101b9fc7fcSBarry Smith } 51116913363SBarry Smith } else if (jac->type == PC_COMPOSITE_MULTIPLICATIVE || jac->type == PC_COMPOSITE_SYMMETRIC_MULTIPLICATIVE) { 51279416396SBarry Smith if (!jac->w1) { 51379416396SBarry Smith ierr = VecDuplicate(x,&jac->w1);CHKERRQ(ierr); 51479416396SBarry Smith ierr = VecDuplicate(x,&jac->w2);CHKERRQ(ierr); 51579416396SBarry Smith } 516efb30889SBarry Smith ierr = VecSet(y,0.0);CHKERRQ(ierr); 5175a9f2f41SSatish Balay ierr = FieldSplitSplitSolveAdd(ilink,x,y);CHKERRQ(ierr); 5183e197d65SBarry Smith cnt = 1; 5195a9f2f41SSatish Balay while (ilink->next) { 5205a9f2f41SSatish Balay ilink = ilink->next; 5213e197d65SBarry Smith if (jac->Afield) { 5223e197d65SBarry Smith /* compute the residual only over the part of the vector needed */ 5233e197d65SBarry Smith ierr = MatMult(jac->Afield[cnt++],y,ilink->x);CHKERRQ(ierr); 5243e197d65SBarry Smith ierr = VecScale(ilink->x,-1.0);CHKERRQ(ierr); 5253e197d65SBarry Smith ierr = VecScatterBegin(ilink->sctx,x,ilink->x,ADD_VALUES,SCATTER_FORWARD);CHKERRQ(ierr); 5263e197d65SBarry Smith ierr = VecScatterEnd(ilink->sctx,x,ilink->x,ADD_VALUES,SCATTER_FORWARD);CHKERRQ(ierr); 5273e197d65SBarry Smith ierr = KSPSolve(ilink->ksp,ilink->x,ilink->y);CHKERRQ(ierr); 5283e197d65SBarry Smith ierr = VecScatterBegin(ilink->sctx,ilink->y,y,ADD_VALUES,SCATTER_REVERSE);CHKERRQ(ierr); 5293e197d65SBarry Smith ierr = VecScatterEnd(ilink->sctx,ilink->y,y,ADD_VALUES,SCATTER_REVERSE);CHKERRQ(ierr); 5303e197d65SBarry Smith } else { 5313e197d65SBarry Smith /* compute the residual over the entire vector */ 5321ab39975SBarry Smith ierr = MatMult(pc->mat,y,jac->w1);CHKERRQ(ierr); 533efb30889SBarry Smith ierr = VecWAXPY(jac->w2,-1.0,jac->w1,x);CHKERRQ(ierr); 5345a9f2f41SSatish Balay ierr = FieldSplitSplitSolveAdd(ilink,jac->w2,y);CHKERRQ(ierr); 53579416396SBarry Smith } 5363e197d65SBarry Smith } 53751f519a2SBarry Smith if (jac->type == PC_COMPOSITE_SYMMETRIC_MULTIPLICATIVE) { 53811755939SBarry Smith cnt -= 2; 53951f519a2SBarry Smith while (ilink->previous) { 54051f519a2SBarry Smith ilink = ilink->previous; 54111755939SBarry Smith if (jac->Afield) { 54211755939SBarry Smith /* compute the residual only over the part of the vector needed */ 54311755939SBarry Smith ierr = MatMult(jac->Afield[cnt--],y,ilink->x);CHKERRQ(ierr); 54411755939SBarry Smith ierr = VecScale(ilink->x,-1.0);CHKERRQ(ierr); 54511755939SBarry Smith ierr = VecScatterBegin(ilink->sctx,x,ilink->x,ADD_VALUES,SCATTER_FORWARD);CHKERRQ(ierr); 54611755939SBarry Smith ierr = VecScatterEnd(ilink->sctx,x,ilink->x,ADD_VALUES,SCATTER_FORWARD);CHKERRQ(ierr); 54711755939SBarry Smith ierr = KSPSolve(ilink->ksp,ilink->x,ilink->y);CHKERRQ(ierr); 54811755939SBarry Smith ierr = VecScatterBegin(ilink->sctx,ilink->y,y,ADD_VALUES,SCATTER_REVERSE);CHKERRQ(ierr); 54911755939SBarry Smith ierr = VecScatterEnd(ilink->sctx,ilink->y,y,ADD_VALUES,SCATTER_REVERSE);CHKERRQ(ierr); 55011755939SBarry Smith } else { 5511ab39975SBarry Smith ierr = MatMult(pc->mat,y,jac->w1);CHKERRQ(ierr); 55251f519a2SBarry Smith ierr = VecWAXPY(jac->w2,-1.0,jac->w1,x);CHKERRQ(ierr); 55351f519a2SBarry Smith ierr = FieldSplitSplitSolveAdd(ilink,jac->w2,y);CHKERRQ(ierr); 55479416396SBarry Smith } 55551f519a2SBarry Smith } 55611755939SBarry Smith } 55716913363SBarry Smith } else SETERRQ1(PETSC_ERR_SUP,"Unsupported or unknown composition",(int) jac->type); 55851f519a2SBarry Smith CHKMEMQ; 5590971522cSBarry Smith PetscFunctionReturn(0); 5600971522cSBarry Smith } 5610971522cSBarry Smith 562421e10b8SBarry Smith #define FieldSplitSplitSolveAddTranspose(ilink,xx,yy) \ 563ca9f406cSSatish Balay (VecScatterBegin(ilink->sctx,xx,ilink->y,INSERT_VALUES,SCATTER_FORWARD) || \ 564ca9f406cSSatish Balay VecScatterEnd(ilink->sctx,xx,ilink->y,INSERT_VALUES,SCATTER_FORWARD) || \ 565421e10b8SBarry Smith KSPSolveTranspose(ilink->ksp,ilink->y,ilink->x) || \ 566ca9f406cSSatish Balay VecScatterBegin(ilink->sctx,ilink->x,yy,ADD_VALUES,SCATTER_REVERSE) || \ 567ca9f406cSSatish Balay VecScatterEnd(ilink->sctx,ilink->x,yy,ADD_VALUES,SCATTER_REVERSE)) 568421e10b8SBarry Smith 569421e10b8SBarry Smith #undef __FUNCT__ 570421e10b8SBarry Smith #define __FUNCT__ "PCApply_FieldSplit" 571421e10b8SBarry Smith static PetscErrorCode PCApplyTranspose_FieldSplit(PC pc,Vec x,Vec y) 572421e10b8SBarry Smith { 573421e10b8SBarry Smith PC_FieldSplit *jac = (PC_FieldSplit*)pc->data; 574421e10b8SBarry Smith PetscErrorCode ierr; 575421e10b8SBarry Smith PC_FieldSplitLink ilink = jac->head; 576421e10b8SBarry Smith 577421e10b8SBarry Smith PetscFunctionBegin; 578421e10b8SBarry Smith CHKMEMQ; 579421e10b8SBarry Smith ierr = VecSetBlockSize(x,jac->bs);CHKERRQ(ierr); 580421e10b8SBarry Smith ierr = VecSetBlockSize(y,jac->bs);CHKERRQ(ierr); 581421e10b8SBarry Smith 582421e10b8SBarry Smith if (jac->type == PC_COMPOSITE_ADDITIVE) { 583421e10b8SBarry Smith if (jac->defaultsplit) { 584421e10b8SBarry Smith ierr = VecStrideGatherAll(x,jac->x,INSERT_VALUES);CHKERRQ(ierr); 585421e10b8SBarry Smith while (ilink) { 586421e10b8SBarry Smith ierr = KSPSolveTranspose(ilink->ksp,ilink->x,ilink->y);CHKERRQ(ierr); 587421e10b8SBarry Smith ilink = ilink->next; 588421e10b8SBarry Smith } 589421e10b8SBarry Smith ierr = VecStrideScatterAll(jac->y,y,INSERT_VALUES);CHKERRQ(ierr); 590421e10b8SBarry Smith } else { 591421e10b8SBarry Smith ierr = VecSet(y,0.0);CHKERRQ(ierr); 592421e10b8SBarry Smith while (ilink) { 593421e10b8SBarry Smith ierr = FieldSplitSplitSolveAddTranspose(ilink,x,y);CHKERRQ(ierr); 594421e10b8SBarry Smith ilink = ilink->next; 595421e10b8SBarry Smith } 596421e10b8SBarry Smith } 597421e10b8SBarry Smith } else { 598421e10b8SBarry Smith if (!jac->w1) { 599421e10b8SBarry Smith ierr = VecDuplicate(x,&jac->w1);CHKERRQ(ierr); 600421e10b8SBarry Smith ierr = VecDuplicate(x,&jac->w2);CHKERRQ(ierr); 601421e10b8SBarry Smith } 602421e10b8SBarry Smith ierr = VecSet(y,0.0);CHKERRQ(ierr); 603421e10b8SBarry Smith if (jac->type == PC_COMPOSITE_SYMMETRIC_MULTIPLICATIVE) { 604421e10b8SBarry Smith ierr = FieldSplitSplitSolveAddTranspose(ilink,x,y);CHKERRQ(ierr); 605421e10b8SBarry Smith while (ilink->next) { 606421e10b8SBarry Smith ilink = ilink->next; 6079989ab13SBarry Smith ierr = MatMultTranspose(pc->mat,y,jac->w1);CHKERRQ(ierr); 608421e10b8SBarry Smith ierr = VecWAXPY(jac->w2,-1.0,jac->w1,x);CHKERRQ(ierr); 609421e10b8SBarry Smith ierr = FieldSplitSplitSolveAddTranspose(ilink,jac->w2,y);CHKERRQ(ierr); 610421e10b8SBarry Smith } 611421e10b8SBarry Smith while (ilink->previous) { 612421e10b8SBarry Smith ilink = ilink->previous; 6139989ab13SBarry Smith ierr = MatMultTranspose(pc->mat,y,jac->w1);CHKERRQ(ierr); 614421e10b8SBarry Smith ierr = VecWAXPY(jac->w2,-1.0,jac->w1,x);CHKERRQ(ierr); 615421e10b8SBarry Smith ierr = FieldSplitSplitSolveAddTranspose(ilink,jac->w2,y);CHKERRQ(ierr); 616421e10b8SBarry Smith } 617421e10b8SBarry Smith } else { 618421e10b8SBarry Smith while (ilink->next) { /* get to last entry in linked list */ 619421e10b8SBarry Smith ilink = ilink->next; 620421e10b8SBarry Smith } 621421e10b8SBarry Smith ierr = FieldSplitSplitSolveAddTranspose(ilink,x,y);CHKERRQ(ierr); 622421e10b8SBarry Smith while (ilink->previous) { 623421e10b8SBarry Smith ilink = ilink->previous; 6249989ab13SBarry Smith ierr = MatMultTranspose(pc->mat,y,jac->w1);CHKERRQ(ierr); 625421e10b8SBarry Smith ierr = VecWAXPY(jac->w2,-1.0,jac->w1,x);CHKERRQ(ierr); 626421e10b8SBarry Smith ierr = FieldSplitSplitSolveAddTranspose(ilink,jac->w2,y);CHKERRQ(ierr); 627421e10b8SBarry Smith } 628421e10b8SBarry Smith } 629421e10b8SBarry Smith } 630421e10b8SBarry Smith CHKMEMQ; 631421e10b8SBarry Smith PetscFunctionReturn(0); 632421e10b8SBarry Smith } 633421e10b8SBarry Smith 6340971522cSBarry Smith #undef __FUNCT__ 6350971522cSBarry Smith #define __FUNCT__ "PCDestroy_FieldSplit" 6360971522cSBarry Smith static PetscErrorCode PCDestroy_FieldSplit(PC pc) 6370971522cSBarry Smith { 6380971522cSBarry Smith PC_FieldSplit *jac = (PC_FieldSplit*)pc->data; 6390971522cSBarry Smith PetscErrorCode ierr; 6405a9f2f41SSatish Balay PC_FieldSplitLink ilink = jac->head,next; 6410971522cSBarry Smith 6420971522cSBarry Smith PetscFunctionBegin; 6435a9f2f41SSatish Balay while (ilink) { 6445a9f2f41SSatish Balay ierr = KSPDestroy(ilink->ksp);CHKERRQ(ierr); 6455a9f2f41SSatish Balay if (ilink->x) {ierr = VecDestroy(ilink->x);CHKERRQ(ierr);} 6465a9f2f41SSatish Balay if (ilink->y) {ierr = VecDestroy(ilink->y);CHKERRQ(ierr);} 6475a9f2f41SSatish Balay if (ilink->sctx) {ierr = VecScatterDestroy(ilink->sctx);CHKERRQ(ierr);} 648704ba839SBarry Smith if (ilink->is) {ierr = ISDestroy(ilink->is);CHKERRQ(ierr);} 6495a9f2f41SSatish Balay next = ilink->next; 650704ba839SBarry Smith ierr = PetscFree(ilink->fields);CHKERRQ(ierr); 651704ba839SBarry Smith ierr = PetscFree(ilink);CHKERRQ(ierr); 6525a9f2f41SSatish Balay ilink = next; 6530971522cSBarry Smith } 65405b42c5fSBarry Smith ierr = PetscFree2(jac->x,jac->y);CHKERRQ(ierr); 655519d70e2SJed Brown if (jac->mat && jac->mat != jac->pmat) {ierr = MatDestroyMatrices(jac->nsplits,&jac->mat);CHKERRQ(ierr);} 65697bbdb24SBarry Smith if (jac->pmat) {ierr = MatDestroyMatrices(jac->nsplits,&jac->pmat);CHKERRQ(ierr);} 65768dd23aaSBarry Smith if (jac->Afield) {ierr = MatDestroyMatrices(jac->nsplits,&jac->Afield);CHKERRQ(ierr);} 65879416396SBarry Smith if (jac->w1) {ierr = VecDestroy(jac->w1);CHKERRQ(ierr);} 65979416396SBarry Smith if (jac->w2) {ierr = VecDestroy(jac->w2);CHKERRQ(ierr);} 6603b224e63SBarry Smith if (jac->schur) {ierr = MatDestroy(jac->schur);CHKERRQ(ierr);} 661084e4875SJed Brown if (jac->schur_user) {ierr = MatDestroy(jac->schur_user);CHKERRQ(ierr);} 662d0f46423SBarry Smith if (jac->kspschur) {ierr = KSPDestroy(jac->kspschur);CHKERRQ(ierr);} 6633b224e63SBarry Smith if (jac->B) {ierr = MatDestroy(jac->B);CHKERRQ(ierr);} 6643b224e63SBarry Smith if (jac->C) {ierr = MatDestroy(jac->C);CHKERRQ(ierr);} 6650971522cSBarry Smith ierr = PetscFree(jac);CHKERRQ(ierr); 6660971522cSBarry Smith PetscFunctionReturn(0); 6670971522cSBarry Smith } 6680971522cSBarry Smith 6690971522cSBarry Smith #undef __FUNCT__ 6700971522cSBarry Smith #define __FUNCT__ "PCSetFromOptions_FieldSplit" 6710971522cSBarry Smith static PetscErrorCode PCSetFromOptions_FieldSplit(PC pc) 6720971522cSBarry Smith { 6731b9fc7fcSBarry Smith PetscErrorCode ierr; 67451f519a2SBarry Smith PetscInt i = 0,nfields,*fields,bs; 675084e4875SJed Brown PetscTruth flg; 6761b9fc7fcSBarry Smith char optionname[128]; 6779dcbbd2bSBarry Smith PC_FieldSplit *jac = (PC_FieldSplit*)pc->data; 6783b224e63SBarry Smith PCCompositeType ctype; 6791b9fc7fcSBarry Smith 6800971522cSBarry Smith PetscFunctionBegin; 6811b9fc7fcSBarry Smith ierr = PetscOptionsHead("FieldSplit options");CHKERRQ(ierr); 682519d70e2SJed Brown ierr = PetscOptionsTruth("-pc_fieldsplit_real_diagonal","Use diagonal blocks of the operator","PCFieldSplitSetRealDiagonal",jac->realdiagonal,&jac->realdiagonal,PETSC_NULL);CHKERRQ(ierr); 68351f519a2SBarry Smith ierr = PetscOptionsInt("-pc_fieldsplit_block_size","Blocksize that defines number of fields","PCFieldSplitSetBlockSize",jac->bs,&bs,&flg);CHKERRQ(ierr); 68451f519a2SBarry Smith if (flg) { 68551f519a2SBarry Smith ierr = PCFieldSplitSetBlockSize(pc,bs);CHKERRQ(ierr); 68651f519a2SBarry Smith } 687704ba839SBarry Smith 6883b224e63SBarry Smith ierr = PetscOptionsEnum("-pc_fieldsplit_type","Type of composition","PCFieldSplitSetType",PCCompositeTypes,(PetscEnum)jac->type,(PetscEnum*)&ctype,&flg);CHKERRQ(ierr); 6893b224e63SBarry Smith if (flg) { 6903b224e63SBarry Smith ierr = PCFieldSplitSetType(pc,ctype);CHKERRQ(ierr); 6913b224e63SBarry Smith } 692d32f9abdSBarry Smith 693c30613efSMatthew Knepley /* Only setup fields once */ 694c30613efSMatthew Knepley if ((jac->bs > 0) && (jac->nsplits == 0)) { 695d32f9abdSBarry Smith /* only allow user to set fields from command line if bs is already known. 696d32f9abdSBarry Smith otherwise user can set them in PCFieldSplitSetDefaults() */ 69751f519a2SBarry Smith ierr = PetscMalloc(jac->bs*sizeof(PetscInt),&fields);CHKERRQ(ierr); 6981b9fc7fcSBarry Smith while (PETSC_TRUE) { 69913f74950SBarry Smith sprintf(optionname,"-pc_fieldsplit_%d_fields",(int)i++); 70051f519a2SBarry Smith nfields = jac->bs; 7011b9fc7fcSBarry Smith ierr = PetscOptionsIntArray(optionname,"Fields in this split","PCFieldSplitSetFields",fields,&nfields,&flg);CHKERRQ(ierr); 7021b9fc7fcSBarry Smith if (!flg) break; 7031b9fc7fcSBarry Smith if (!nfields) SETERRQ(PETSC_ERR_USER,"Cannot list zero fields"); 7041b9fc7fcSBarry Smith ierr = PCFieldSplitSetFields(pc,nfields,fields);CHKERRQ(ierr); 7051b9fc7fcSBarry Smith } 70651f519a2SBarry Smith ierr = PetscFree(fields);CHKERRQ(ierr); 707d32f9abdSBarry Smith } 708084e4875SJed 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); 7091b9fc7fcSBarry Smith ierr = PetscOptionsTail();CHKERRQ(ierr); 7100971522cSBarry Smith PetscFunctionReturn(0); 7110971522cSBarry Smith } 7120971522cSBarry Smith 7130971522cSBarry Smith /*------------------------------------------------------------------------------------*/ 7140971522cSBarry Smith 7150971522cSBarry Smith EXTERN_C_BEGIN 7160971522cSBarry Smith #undef __FUNCT__ 7170971522cSBarry Smith #define __FUNCT__ "PCFieldSplitSetFields_FieldSplit" 718dba47a55SKris Buschelman PetscErrorCode PETSCKSP_DLLEXPORT PCFieldSplitSetFields_FieldSplit(PC pc,PetscInt n,PetscInt *fields) 7190971522cSBarry Smith { 72097bbdb24SBarry Smith PC_FieldSplit *jac = (PC_FieldSplit*)pc->data; 7210971522cSBarry Smith PetscErrorCode ierr; 7225a9f2f41SSatish Balay PC_FieldSplitLink ilink,next = jac->head; 72369a612a9SBarry Smith char prefix[128]; 72451f519a2SBarry Smith PetscInt i; 7250971522cSBarry Smith 7260971522cSBarry Smith PetscFunctionBegin; 7270971522cSBarry Smith if (n <= 0) SETERRQ(PETSC_ERR_ARG_OUTOFRANGE,"Negative number of fields requested"); 72851f519a2SBarry Smith for (i=0; i<n; i++) { 72951f519a2SBarry Smith if (fields[i] >= jac->bs) SETERRQ2(PETSC_ERR_ARG_OUTOFRANGE,"Field %D requested but only %D exist",fields[i],jac->bs); 73051f519a2SBarry Smith if (fields[i] < 0) SETERRQ1(PETSC_ERR_ARG_OUTOFRANGE,"Negative field %D requested",fields[i]); 73151f519a2SBarry Smith } 732704ba839SBarry Smith ierr = PetscNew(struct _PC_FieldSplitLink,&ilink);CHKERRQ(ierr); 733704ba839SBarry Smith ierr = PetscMalloc(n*sizeof(PetscInt),&ilink->fields);CHKERRQ(ierr); 7345a9f2f41SSatish Balay ierr = PetscMemcpy(ilink->fields,fields,n*sizeof(PetscInt));CHKERRQ(ierr); 7355a9f2f41SSatish Balay ilink->nfields = n; 7365a9f2f41SSatish Balay ilink->next = PETSC_NULL; 7377adad957SLisandro Dalcin ierr = KSPCreate(((PetscObject)pc)->comm,&ilink->ksp);CHKERRQ(ierr); 7381cee3971SBarry Smith ierr = PetscObjectIncrementTabLevel((PetscObject)ilink->ksp,(PetscObject)pc,1);CHKERRQ(ierr); 7395a9f2f41SSatish Balay ierr = KSPSetType(ilink->ksp,KSPPREONLY);CHKERRQ(ierr); 74069a612a9SBarry Smith 7417adad957SLisandro Dalcin if (((PetscObject)pc)->prefix) { 7427adad957SLisandro Dalcin sprintf(prefix,"%sfieldsplit_%d_",((PetscObject)pc)->prefix,(int)jac->nsplits); 74369a612a9SBarry Smith } else { 74413f74950SBarry Smith sprintf(prefix,"fieldsplit_%d_",(int)jac->nsplits); 74569a612a9SBarry Smith } 7465a9f2f41SSatish Balay ierr = KSPSetOptionsPrefix(ilink->ksp,prefix);CHKERRQ(ierr); 7470971522cSBarry Smith 7480971522cSBarry Smith if (!next) { 7495a9f2f41SSatish Balay jac->head = ilink; 75051f519a2SBarry Smith ilink->previous = PETSC_NULL; 7510971522cSBarry Smith } else { 7520971522cSBarry Smith while (next->next) { 7530971522cSBarry Smith next = next->next; 7540971522cSBarry Smith } 7555a9f2f41SSatish Balay next->next = ilink; 75651f519a2SBarry Smith ilink->previous = next; 7570971522cSBarry Smith } 7580971522cSBarry Smith jac->nsplits++; 7590971522cSBarry Smith PetscFunctionReturn(0); 7600971522cSBarry Smith } 7610971522cSBarry Smith EXTERN_C_END 7620971522cSBarry Smith 763e69d4d44SBarry Smith EXTERN_C_BEGIN 764e69d4d44SBarry Smith #undef __FUNCT__ 765e69d4d44SBarry Smith #define __FUNCT__ "PCFieldSplitGetSubKSP_FieldSplit_Schur" 766e69d4d44SBarry Smith PetscErrorCode PETSCKSP_DLLEXPORT PCFieldSplitGetSubKSP_FieldSplit_Schur(PC pc,PetscInt *n,KSP **subksp) 767e69d4d44SBarry Smith { 768e69d4d44SBarry Smith PC_FieldSplit *jac = (PC_FieldSplit*)pc->data; 769e69d4d44SBarry Smith PetscErrorCode ierr; 770e69d4d44SBarry Smith 771e69d4d44SBarry Smith PetscFunctionBegin; 772519d70e2SJed Brown ierr = PetscMalloc(jac->nsplits*sizeof(KSP),subksp);CHKERRQ(ierr); 773e69d4d44SBarry Smith ierr = MatSchurComplementGetKSP(jac->schur,*subksp);CHKERRQ(ierr); 774e69d4d44SBarry Smith (*subksp)[1] = jac->kspschur; 775084e4875SJed Brown *n = jac->nsplits; 776e69d4d44SBarry Smith PetscFunctionReturn(0); 777e69d4d44SBarry Smith } 778e69d4d44SBarry Smith EXTERN_C_END 7790971522cSBarry Smith 7800971522cSBarry Smith EXTERN_C_BEGIN 7810971522cSBarry Smith #undef __FUNCT__ 78269a612a9SBarry Smith #define __FUNCT__ "PCFieldSplitGetSubKSP_FieldSplit" 783dba47a55SKris Buschelman PetscErrorCode PETSCKSP_DLLEXPORT PCFieldSplitGetSubKSP_FieldSplit(PC pc,PetscInt *n,KSP **subksp) 7840971522cSBarry Smith { 7850971522cSBarry Smith PC_FieldSplit *jac = (PC_FieldSplit*)pc->data; 7860971522cSBarry Smith PetscErrorCode ierr; 7870971522cSBarry Smith PetscInt cnt = 0; 7885a9f2f41SSatish Balay PC_FieldSplitLink ilink = jac->head; 7890971522cSBarry Smith 7900971522cSBarry Smith PetscFunctionBegin; 79169a612a9SBarry Smith ierr = PetscMalloc(jac->nsplits*sizeof(KSP*),subksp);CHKERRQ(ierr); 7925a9f2f41SSatish Balay while (ilink) { 7935a9f2f41SSatish Balay (*subksp)[cnt++] = ilink->ksp; 7945a9f2f41SSatish Balay ilink = ilink->next; 7950971522cSBarry Smith } 7960971522cSBarry Smith if (cnt != jac->nsplits) SETERRQ2(PETSC_ERR_PLIB,"Corrupt PCFIELDSPLIT object: number splits in linked list %D in object %D",cnt,jac->nsplits); 7970971522cSBarry Smith *n = jac->nsplits; 7980971522cSBarry Smith PetscFunctionReturn(0); 7990971522cSBarry Smith } 8000971522cSBarry Smith EXTERN_C_END 8010971522cSBarry Smith 802704ba839SBarry Smith EXTERN_C_BEGIN 803704ba839SBarry Smith #undef __FUNCT__ 804704ba839SBarry Smith #define __FUNCT__ "PCFieldSplitSetIS_FieldSplit" 805704ba839SBarry Smith PetscErrorCode PETSCKSP_DLLEXPORT PCFieldSplitSetIS_FieldSplit(PC pc,IS is) 806704ba839SBarry Smith { 807704ba839SBarry Smith PC_FieldSplit *jac = (PC_FieldSplit*)pc->data; 808704ba839SBarry Smith PetscErrorCode ierr; 809704ba839SBarry Smith PC_FieldSplitLink ilink, next = jac->head; 810704ba839SBarry Smith char prefix[128]; 811704ba839SBarry Smith 812704ba839SBarry Smith PetscFunctionBegin; 81316913363SBarry Smith ierr = PetscNew(struct _PC_FieldSplitLink,&ilink);CHKERRQ(ierr); 8141ab39975SBarry Smith ilink->is = is; 8151ab39975SBarry Smith ierr = PetscObjectReference((PetscObject)is);CHKERRQ(ierr); 816704ba839SBarry Smith ilink->next = PETSC_NULL; 817704ba839SBarry Smith ierr = KSPCreate(((PetscObject)pc)->comm,&ilink->ksp);CHKERRQ(ierr); 8181cee3971SBarry Smith ierr = PetscObjectIncrementTabLevel((PetscObject)ilink->ksp,(PetscObject)pc,1);CHKERRQ(ierr); 819704ba839SBarry Smith ierr = KSPSetType(ilink->ksp,KSPPREONLY);CHKERRQ(ierr); 820704ba839SBarry Smith 821704ba839SBarry Smith if (((PetscObject)pc)->prefix) { 822704ba839SBarry Smith sprintf(prefix,"%sfieldsplit_%d_",((PetscObject)pc)->prefix,(int)jac->nsplits); 823704ba839SBarry Smith } else { 824704ba839SBarry Smith sprintf(prefix,"fieldsplit_%d_",(int)jac->nsplits); 825704ba839SBarry Smith } 826704ba839SBarry Smith ierr = KSPSetOptionsPrefix(ilink->ksp,prefix);CHKERRQ(ierr); 827704ba839SBarry Smith 828704ba839SBarry Smith if (!next) { 829704ba839SBarry Smith jac->head = ilink; 830704ba839SBarry Smith ilink->previous = PETSC_NULL; 831704ba839SBarry Smith } else { 832704ba839SBarry Smith while (next->next) { 833704ba839SBarry Smith next = next->next; 834704ba839SBarry Smith } 835704ba839SBarry Smith next->next = ilink; 836704ba839SBarry Smith ilink->previous = next; 837704ba839SBarry Smith } 838704ba839SBarry Smith jac->nsplits++; 839704ba839SBarry Smith 840704ba839SBarry Smith PetscFunctionReturn(0); 841704ba839SBarry Smith } 842704ba839SBarry Smith EXTERN_C_END 843704ba839SBarry Smith 8440971522cSBarry Smith #undef __FUNCT__ 8450971522cSBarry Smith #define __FUNCT__ "PCFieldSplitSetFields" 8460971522cSBarry Smith /*@ 8470971522cSBarry Smith PCFieldSplitSetFields - Sets the fields for one particular split in the field split preconditioner 8480971522cSBarry Smith 8490971522cSBarry Smith Collective on PC 8500971522cSBarry Smith 8510971522cSBarry Smith Input Parameters: 8520971522cSBarry Smith + pc - the preconditioner context 8530971522cSBarry Smith . n - the number of fields in this split 8540971522cSBarry Smith . fields - the fields in this split 8550971522cSBarry Smith 8560971522cSBarry Smith Level: intermediate 8570971522cSBarry Smith 858d32f9abdSBarry Smith Notes: Use PCFieldSplitSetIS() to set a completely general set of indices as a field. 859d32f9abdSBarry Smith 860d32f9abdSBarry Smith The PCFieldSplitSetFields() is for defining fields as a strided blocks. For example, if the block 861d32f9abdSBarry 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 862d32f9abdSBarry Smith 0xx3xx6xx9xx12 ... x1xx4xx7xx ... xx2xx5xx8xx.. 01x34x67x... 0x1x3x5x7.. x12x45x78x.... 863d32f9abdSBarry Smith where the numbered entries indicate what is in the field. 864d32f9abdSBarry Smith 865d32f9abdSBarry Smith .seealso: PCFieldSplitGetSubKSP(), PCFIELDSPLIT, PCFieldSplitSetBlockSize(), PCFieldSplitSetIS() 8660971522cSBarry Smith 8670971522cSBarry Smith @*/ 868dba47a55SKris Buschelman PetscErrorCode PETSCKSP_DLLEXPORT PCFieldSplitSetFields(PC pc,PetscInt n, PetscInt *fields) 8690971522cSBarry Smith { 8700971522cSBarry Smith PetscErrorCode ierr,(*f)(PC,PetscInt,PetscInt *); 8710971522cSBarry Smith 8720971522cSBarry Smith PetscFunctionBegin; 8730971522cSBarry Smith PetscValidHeaderSpecific(pc,PC_COOKIE,1); 8740971522cSBarry Smith ierr = PetscObjectQueryFunction((PetscObject)pc,"PCFieldSplitSetFields_C",(void (**)(void))&f);CHKERRQ(ierr); 8750971522cSBarry Smith if (f) { 8760971522cSBarry Smith ierr = (*f)(pc,n,fields);CHKERRQ(ierr); 8770971522cSBarry Smith } 8780971522cSBarry Smith PetscFunctionReturn(0); 8790971522cSBarry Smith } 8800971522cSBarry Smith 8810971522cSBarry Smith #undef __FUNCT__ 882704ba839SBarry Smith #define __FUNCT__ "PCFieldSplitSetIS" 883704ba839SBarry Smith /*@ 884704ba839SBarry Smith PCFieldSplitSetIS - Sets the exact elements for field 885704ba839SBarry Smith 886704ba839SBarry Smith Collective on PC 887704ba839SBarry Smith 888704ba839SBarry Smith Input Parameters: 889704ba839SBarry Smith + pc - the preconditioner context 890704ba839SBarry Smith . is - the index set that defines the vector elements in this field 891704ba839SBarry Smith 892d32f9abdSBarry Smith 893d32f9abdSBarry Smith Notes: Use PCFieldSplitSetFields(), for fields defined by strided types. 894d32f9abdSBarry Smith 895704ba839SBarry Smith Level: intermediate 896704ba839SBarry Smith 897704ba839SBarry Smith .seealso: PCFieldSplitGetSubKSP(), PCFIELDSPLIT, PCFieldSplitSetBlockSize() 898704ba839SBarry Smith 899704ba839SBarry Smith @*/ 900704ba839SBarry Smith PetscErrorCode PETSCKSP_DLLEXPORT PCFieldSplitSetIS(PC pc,IS is) 901704ba839SBarry Smith { 902704ba839SBarry Smith PetscErrorCode ierr,(*f)(PC,IS); 903704ba839SBarry Smith 904704ba839SBarry Smith PetscFunctionBegin; 905704ba839SBarry Smith PetscValidHeaderSpecific(pc,PC_COOKIE,1); 906704ba839SBarry Smith PetscValidHeaderSpecific(is,IS_COOKIE,1); 907704ba839SBarry Smith ierr = PetscObjectQueryFunction((PetscObject)pc,"PCFieldSplitSetIS_C",(void (**)(void))&f);CHKERRQ(ierr); 908704ba839SBarry Smith if (f) { 909704ba839SBarry Smith ierr = (*f)(pc,is);CHKERRQ(ierr); 910704ba839SBarry Smith } 911704ba839SBarry Smith PetscFunctionReturn(0); 912704ba839SBarry Smith } 913704ba839SBarry Smith 914704ba839SBarry Smith #undef __FUNCT__ 91551f519a2SBarry Smith #define __FUNCT__ "PCFieldSplitSetBlockSize" 91651f519a2SBarry Smith /*@ 91751f519a2SBarry Smith PCFieldSplitSetBlockSize - Sets the block size for defining where fields start in the 91851f519a2SBarry Smith fieldsplit preconditioner. If not set the matrix block size is used. 91951f519a2SBarry Smith 92051f519a2SBarry Smith Collective on PC 92151f519a2SBarry Smith 92251f519a2SBarry Smith Input Parameters: 92351f519a2SBarry Smith + pc - the preconditioner context 92451f519a2SBarry Smith - bs - the block size 92551f519a2SBarry Smith 92651f519a2SBarry Smith Level: intermediate 92751f519a2SBarry Smith 92851f519a2SBarry Smith .seealso: PCFieldSplitGetSubKSP(), PCFIELDSPLIT, PCFieldSplitSetFields() 92951f519a2SBarry Smith 93051f519a2SBarry Smith @*/ 93151f519a2SBarry Smith PetscErrorCode PETSCKSP_DLLEXPORT PCFieldSplitSetBlockSize(PC pc,PetscInt bs) 93251f519a2SBarry Smith { 93351f519a2SBarry Smith PetscErrorCode ierr,(*f)(PC,PetscInt); 93451f519a2SBarry Smith 93551f519a2SBarry Smith PetscFunctionBegin; 93651f519a2SBarry Smith PetscValidHeaderSpecific(pc,PC_COOKIE,1); 93751f519a2SBarry Smith ierr = PetscObjectQueryFunction((PetscObject)pc,"PCFieldSplitSetBlockSize_C",(void (**)(void))&f);CHKERRQ(ierr); 93851f519a2SBarry Smith if (f) { 93951f519a2SBarry Smith ierr = (*f)(pc,bs);CHKERRQ(ierr); 94051f519a2SBarry Smith } 94151f519a2SBarry Smith PetscFunctionReturn(0); 94251f519a2SBarry Smith } 94351f519a2SBarry Smith 94451f519a2SBarry Smith #undef __FUNCT__ 94569a612a9SBarry Smith #define __FUNCT__ "PCFieldSplitGetSubKSP" 9460971522cSBarry Smith /*@C 94769a612a9SBarry Smith PCFieldSplitGetSubKSP - Gets the KSP contexts for all splits 9480971522cSBarry Smith 94969a612a9SBarry Smith Collective on KSP 9500971522cSBarry Smith 9510971522cSBarry Smith Input Parameter: 9520971522cSBarry Smith . pc - the preconditioner context 9530971522cSBarry Smith 9540971522cSBarry Smith Output Parameters: 9550971522cSBarry Smith + n - the number of split 95669a612a9SBarry Smith - pc - the array of KSP contexts 9570971522cSBarry Smith 9580971522cSBarry Smith Note: 959d32f9abdSBarry Smith After PCFieldSplitGetSubKSP() the array of KSPs IS to be freed by the user 960d32f9abdSBarry Smith (not the KSP just the array that contains them). 9610971522cSBarry Smith 96269a612a9SBarry Smith You must call KSPSetUp() before calling PCFieldSplitGetSubKSP(). 9630971522cSBarry Smith 9640971522cSBarry Smith Level: advanced 9650971522cSBarry Smith 9660971522cSBarry Smith .seealso: PCFIELDSPLIT 9670971522cSBarry Smith @*/ 968dba47a55SKris Buschelman PetscErrorCode PETSCKSP_DLLEXPORT PCFieldSplitGetSubKSP(PC pc,PetscInt *n,KSP *subksp[]) 9690971522cSBarry Smith { 97069a612a9SBarry Smith PetscErrorCode ierr,(*f)(PC,PetscInt*,KSP **); 9710971522cSBarry Smith 9720971522cSBarry Smith PetscFunctionBegin; 9730971522cSBarry Smith PetscValidHeaderSpecific(pc,PC_COOKIE,1); 9740971522cSBarry Smith PetscValidIntPointer(n,2); 97569a612a9SBarry Smith ierr = PetscObjectQueryFunction((PetscObject)pc,"PCFieldSplitGetSubKSP_C",(void (**)(void))&f);CHKERRQ(ierr); 9760971522cSBarry Smith if (f) { 97769a612a9SBarry Smith ierr = (*f)(pc,n,subksp);CHKERRQ(ierr); 9780971522cSBarry Smith } else { 97969a612a9SBarry Smith SETERRQ(PETSC_ERR_ARG_WRONG,"Cannot get subksp for this type of PC"); 9800971522cSBarry Smith } 9810971522cSBarry Smith PetscFunctionReturn(0); 9820971522cSBarry Smith } 9830971522cSBarry Smith 984e69d4d44SBarry Smith #undef __FUNCT__ 985e69d4d44SBarry Smith #define __FUNCT__ "PCFieldSplitSchurPrecondition" 986e69d4d44SBarry Smith /*@ 987e69d4d44SBarry Smith PCFieldSplitSchurPrecondition - Indicates if the Schur complement is preconditioned by a preconditioner constructed by the 988e69d4d44SBarry Smith D matrix. Otherwise no preconditioner is used. 989e69d4d44SBarry Smith 990e69d4d44SBarry Smith Collective on PC 991e69d4d44SBarry Smith 992e69d4d44SBarry Smith Input Parameters: 993e69d4d44SBarry Smith + pc - the preconditioner context 994084e4875SJed Brown . ptype - which matrix to use for preconditioning the Schur complement 995084e4875SJed Brown - userpre - matrix to use for preconditioning, or PETSC_NULL 996084e4875SJed Brown 997084e4875SJed Brown Notes: 998084e4875SJed Brown The default is to use the block on the diagonal of the preconditioning matrix. This is D, in the (1,1) position. 999084e4875SJed Brown There are currently no preconditioners that work directly with the Schur complement so setting 1000084e4875SJed Brown PC_FIELDSPLIT_SCHUR_PRE_SELF is observationally equivalent to -fieldsplit_1_pc_type none. 1001e69d4d44SBarry Smith 1002e69d4d44SBarry Smith Options Database: 1003084e4875SJed Brown . -pc_fieldsplit_schur_precondition <self,user,diag> default is diag 1004e69d4d44SBarry Smith 1005e69d4d44SBarry Smith Level: intermediate 1006e69d4d44SBarry Smith 1007084e4875SJed Brown .seealso: PCFieldSplitGetSubKSP(), PCFIELDSPLIT, PCFieldSplitSetFields(), PCFieldSplitSchurPreType 1008e69d4d44SBarry Smith 1009e69d4d44SBarry Smith @*/ 1010084e4875SJed Brown PetscErrorCode PETSCKSP_DLLEXPORT PCFieldSplitSchurPrecondition(PC pc,PCFieldSplitSchurPreType ptype,Mat pre) 1011e69d4d44SBarry Smith { 1012084e4875SJed Brown PetscErrorCode ierr,(*f)(PC,PCFieldSplitSchurPreType,Mat); 1013e69d4d44SBarry Smith 1014e69d4d44SBarry Smith PetscFunctionBegin; 1015e69d4d44SBarry Smith PetscValidHeaderSpecific(pc,PC_COOKIE,1); 1016e69d4d44SBarry Smith ierr = PetscObjectQueryFunction((PetscObject)pc,"PCFieldSplitSchurPrecondition_C",(void (**)(void))&f);CHKERRQ(ierr); 1017e69d4d44SBarry Smith if (f) { 1018084e4875SJed Brown ierr = (*f)(pc,ptype,pre);CHKERRQ(ierr); 1019e69d4d44SBarry Smith } 1020e69d4d44SBarry Smith PetscFunctionReturn(0); 1021e69d4d44SBarry Smith } 1022e69d4d44SBarry Smith 1023e69d4d44SBarry Smith EXTERN_C_BEGIN 1024e69d4d44SBarry Smith #undef __FUNCT__ 1025e69d4d44SBarry Smith #define __FUNCT__ "PCFieldSplitSchurPrecondition_FieldSplit" 1026084e4875SJed Brown PetscErrorCode PETSCKSP_DLLEXPORT PCFieldSplitSchurPrecondition_FieldSplit(PC pc,PCFieldSplitSchurPreType ptype,Mat pre) 1027e69d4d44SBarry Smith { 1028e69d4d44SBarry Smith PC_FieldSplit *jac = (PC_FieldSplit*)pc->data; 1029084e4875SJed Brown PetscErrorCode ierr; 1030e69d4d44SBarry Smith 1031e69d4d44SBarry Smith PetscFunctionBegin; 1032084e4875SJed Brown jac->schurpre = ptype; 1033084e4875SJed Brown if (pre) { 1034084e4875SJed Brown if (jac->schur_user) {ierr = MatDestroy(jac->schur_user);CHKERRQ(ierr);} 1035084e4875SJed Brown jac->schur_user = pre; 1036084e4875SJed Brown ierr = PetscObjectReference((PetscObject)jac->schur_user);CHKERRQ(ierr); 1037084e4875SJed Brown } 1038e69d4d44SBarry Smith PetscFunctionReturn(0); 1039e69d4d44SBarry Smith } 1040e69d4d44SBarry Smith EXTERN_C_END 1041e69d4d44SBarry Smith 104230ad9308SMatthew Knepley #undef __FUNCT__ 104330ad9308SMatthew Knepley #define __FUNCT__ "PCFieldSplitGetSchurBlocks" 104430ad9308SMatthew Knepley /*@C 104530ad9308SMatthew Knepley PCFieldSplitGetSchurBlocks - Gets the all matrix blocks for the Schur complement 104630ad9308SMatthew Knepley 104730ad9308SMatthew Knepley Collective on KSP 104830ad9308SMatthew Knepley 104930ad9308SMatthew Knepley Input Parameter: 105030ad9308SMatthew Knepley . pc - the preconditioner context 105130ad9308SMatthew Knepley 105230ad9308SMatthew Knepley Output Parameters: 105330ad9308SMatthew Knepley + A - the (0,0) block 105430ad9308SMatthew Knepley . B - the (0,1) block 105530ad9308SMatthew Knepley . C - the (1,0) block 105630ad9308SMatthew Knepley - D - the (1,1) block 105730ad9308SMatthew Knepley 105830ad9308SMatthew Knepley Level: advanced 105930ad9308SMatthew Knepley 106030ad9308SMatthew Knepley .seealso: PCFIELDSPLIT 106130ad9308SMatthew Knepley @*/ 106230ad9308SMatthew Knepley PetscErrorCode PETSCKSP_DLLEXPORT PCFieldSplitGetSchurBlocks(PC pc,Mat *A,Mat *B,Mat *C, Mat *D) 106330ad9308SMatthew Knepley { 106430ad9308SMatthew Knepley PC_FieldSplit *jac = (PC_FieldSplit *) pc->data; 106530ad9308SMatthew Knepley 106630ad9308SMatthew Knepley PetscFunctionBegin; 106730ad9308SMatthew Knepley PetscValidHeaderSpecific(pc,PC_COOKIE,1); 1068cf8ad460SMatthew Knepley if (jac->type != PC_COMPOSITE_SCHUR) {SETERRQ(PETSC_ERR_ARG_WRONG, "FieldSplit is not using a Schur complement approach.");} 106930ad9308SMatthew Knepley if (A) *A = jac->pmat[0]; 107030ad9308SMatthew Knepley if (B) *B = jac->B; 107130ad9308SMatthew Knepley if (C) *C = jac->C; 107230ad9308SMatthew Knepley if (D) *D = jac->pmat[1]; 107330ad9308SMatthew Knepley PetscFunctionReturn(0); 107430ad9308SMatthew Knepley } 107530ad9308SMatthew Knepley 107679416396SBarry Smith EXTERN_C_BEGIN 107779416396SBarry Smith #undef __FUNCT__ 107879416396SBarry Smith #define __FUNCT__ "PCFieldSplitSetType_FieldSplit" 1079dba47a55SKris Buschelman PetscErrorCode PETSCKSP_DLLEXPORT PCFieldSplitSetType_FieldSplit(PC pc,PCCompositeType type) 108079416396SBarry Smith { 108179416396SBarry Smith PC_FieldSplit *jac = (PC_FieldSplit*)pc->data; 1082e69d4d44SBarry Smith PetscErrorCode ierr; 108379416396SBarry Smith 108479416396SBarry Smith PetscFunctionBegin; 108579416396SBarry Smith jac->type = type; 10863b224e63SBarry Smith if (type == PC_COMPOSITE_SCHUR) { 10873b224e63SBarry Smith pc->ops->apply = PCApply_FieldSplit_Schur; 10883b224e63SBarry Smith pc->ops->view = PCView_FieldSplit_Schur; 1089e69d4d44SBarry Smith ierr = PetscObjectComposeFunctionDynamic((PetscObject)pc,"PCFieldSplitGetSubKSP_C","PCFieldSplitGetSubKSP_FieldSplit_Schur",PCFieldSplitGetSubKSP_FieldSplit_Schur);CHKERRQ(ierr); 1090e69d4d44SBarry Smith ierr = PetscObjectComposeFunctionDynamic((PetscObject)pc,"PCFieldSplitSchurPrecondition_C","PCFieldSplitSchurPrecondition_FieldSplit",PCFieldSplitSchurPrecondition_FieldSplit);CHKERRQ(ierr); 1091e69d4d44SBarry Smith 10923b224e63SBarry Smith } else { 10933b224e63SBarry Smith pc->ops->apply = PCApply_FieldSplit; 10943b224e63SBarry Smith pc->ops->view = PCView_FieldSplit; 1095e69d4d44SBarry Smith ierr = PetscObjectComposeFunctionDynamic((PetscObject)pc,"PCFieldSplitGetSubKSP_C","PCFieldSplitGetSubKSP_FieldSplit",PCFieldSplitGetSubKSP_FieldSplit);CHKERRQ(ierr); 10969e7d6b0aSBarry Smith ierr = PetscObjectComposeFunctionDynamic((PetscObject)pc,"PCFieldSplitSchurPrecondition_C","",0);CHKERRQ(ierr); 10973b224e63SBarry Smith } 109879416396SBarry Smith PetscFunctionReturn(0); 109979416396SBarry Smith } 110079416396SBarry Smith EXTERN_C_END 110179416396SBarry Smith 110251f519a2SBarry Smith EXTERN_C_BEGIN 110351f519a2SBarry Smith #undef __FUNCT__ 110451f519a2SBarry Smith #define __FUNCT__ "PCFieldSplitSetBlockSize_FieldSplit" 110551f519a2SBarry Smith PetscErrorCode PETSCKSP_DLLEXPORT PCFieldSplitSetBlockSize_FieldSplit(PC pc,PetscInt bs) 110651f519a2SBarry Smith { 110751f519a2SBarry Smith PC_FieldSplit *jac = (PC_FieldSplit*)pc->data; 110851f519a2SBarry Smith 110951f519a2SBarry Smith PetscFunctionBegin; 111051f519a2SBarry Smith if (bs < 1) SETERRQ1(PETSC_ERR_ARG_OUTOFRANGE,"Blocksize must be positive, you gave %D",bs); 111151f519a2SBarry Smith if (jac->bs > 0 && jac->bs != bs) SETERRQ2(PETSC_ERR_ARG_WRONGSTATE,"Cannot change fieldsplit blocksize from %D to %D after it has been set",jac->bs,bs); 111251f519a2SBarry Smith jac->bs = bs; 111351f519a2SBarry Smith PetscFunctionReturn(0); 111451f519a2SBarry Smith } 111551f519a2SBarry Smith EXTERN_C_END 111651f519a2SBarry Smith 111779416396SBarry Smith #undef __FUNCT__ 111879416396SBarry Smith #define __FUNCT__ "PCFieldSplitSetType" 1119bc08b0f1SBarry Smith /*@ 112079416396SBarry Smith PCFieldSplitSetType - Sets the type of fieldsplit preconditioner. 112179416396SBarry Smith 112279416396SBarry Smith Collective on PC 112379416396SBarry Smith 112479416396SBarry Smith Input Parameter: 112579416396SBarry Smith . pc - the preconditioner context 112681540f2fSBarry Smith . type - PC_COMPOSITE_ADDITIVE, PC_COMPOSITE_MULTIPLICATIVE (default), PC_COMPOSITE_SYMMETRIC_MULTIPLICATIVE, PC_COMPOSITE_SPECIAL, PC_COMPOSITE_SCHUR 112779416396SBarry Smith 112879416396SBarry Smith Options Database Key: 1129a4efd8eaSMatthew Knepley . -pc_fieldsplit_type <type: one of multiplicative, additive, symmetric_multiplicative, special, schur> - Sets fieldsplit preconditioner type 113079416396SBarry Smith 113179416396SBarry Smith Level: Developer 113279416396SBarry Smith 113379416396SBarry Smith .keywords: PC, set, type, composite preconditioner, additive, multiplicative 113479416396SBarry Smith 113579416396SBarry Smith .seealso: PCCompositeSetType() 113679416396SBarry Smith 113779416396SBarry Smith @*/ 1138dba47a55SKris Buschelman PetscErrorCode PETSCKSP_DLLEXPORT PCFieldSplitSetType(PC pc,PCCompositeType type) 113979416396SBarry Smith { 114079416396SBarry Smith PetscErrorCode ierr,(*f)(PC,PCCompositeType); 114179416396SBarry Smith 114279416396SBarry Smith PetscFunctionBegin; 114379416396SBarry Smith PetscValidHeaderSpecific(pc,PC_COOKIE,1); 114479416396SBarry Smith ierr = PetscObjectQueryFunction((PetscObject)pc,"PCFieldSplitSetType_C",(void (**)(void))&f);CHKERRQ(ierr); 114579416396SBarry Smith if (f) { 114679416396SBarry Smith ierr = (*f)(pc,type);CHKERRQ(ierr); 114779416396SBarry Smith } 114879416396SBarry Smith PetscFunctionReturn(0); 114979416396SBarry Smith } 115079416396SBarry Smith 11510971522cSBarry Smith /* -------------------------------------------------------------------------------------*/ 11520971522cSBarry Smith /*MC 1153a8c7a070SBarry Smith PCFIELDSPLIT - Preconditioner created by combining separate preconditioners for individual 11540971522cSBarry Smith fields or groups of fields 11550971522cSBarry Smith 11560971522cSBarry Smith 1157edf189efSBarry Smith To set options on the solvers for each block append -fieldsplit_ to all the PC 1158edf189efSBarry Smith options database keys. For example, -fieldsplit_pc_type ilu -fieldsplit_pc_factor_levels 1 11590971522cSBarry Smith 1160a8c7a070SBarry Smith To set the options on the solvers separate for each block call PCFieldSplitGetSubKSP() 116169a612a9SBarry Smith and set the options directly on the resulting KSP object 11620971522cSBarry Smith 11630971522cSBarry Smith Level: intermediate 11640971522cSBarry Smith 116579416396SBarry Smith Options Database Keys: 116681540f2fSBarry Smith + -pc_fieldsplit_%d_fields <a,b,..> - indicates the fields to be used in the %d'th split 116781540f2fSBarry Smith . -pc_fieldsplit_default - automatically add any fields to additional splits that have not 116881540f2fSBarry Smith been supplied explicitly by -pc_fieldsplit_%d_fields 116981540f2fSBarry Smith . -pc_fieldsplit_block_size <bs> - size of block that defines fields (i.e. there are bs fields) 117081540f2fSBarry Smith . -pc_fieldsplit_type <additive,multiplicative,schur,symmetric_multiplicative> 1171e69d4d44SBarry Smith . -pc_fieldsplit_schur_precondition <true,false> default is true 117279416396SBarry Smith 1173edf189efSBarry Smith - Options prefix for inner solvers when using Schur complement preconditioner are -fieldsplit_0_ and -fieldsplit_1_ 11743b224e63SBarry Smith for all other solvers they are -fieldsplit_%d_ for the dth field, use -fieldsplit_ for all fields 11753b224e63SBarry Smith 11763b224e63SBarry Smith 1177d32f9abdSBarry Smith Notes: use PCFieldSplitSetFields() to set fields defined by "strided" entries and PCFieldSplitSetIS() 1178d32f9abdSBarry Smith to define a field by an arbitrary collection of entries. 1179d32f9abdSBarry Smith 1180d32f9abdSBarry Smith If no fields are set the default is used. The fields are defined by entries strided by bs, 1181d32f9abdSBarry Smith beginning at 0 then 1, etc to bs-1. The block size can be set with PCFieldSplitSetBlockSize(), 1182d32f9abdSBarry Smith if this is not called the block size defaults to the blocksize of the second matrix passed 1183d32f9abdSBarry Smith to KSPSetOperators()/PCSetOperators(). 1184d32f9abdSBarry Smith 1185d32f9abdSBarry Smith Currently for the multiplicative version, the updated residual needed for the next field 1186d32f9abdSBarry Smith solve is computed via a matrix vector product over the entire array. An optimization would be 1187d32f9abdSBarry Smith to update the residual only for the part of the right hand side associated with the next field 1188d32f9abdSBarry Smith solve. (This would involve more MatGetSubMatrix() calls or some other mechanism to compute the 1189d32f9abdSBarry Smith part of the matrix needed to just update part of the residual). 1190d32f9abdSBarry Smith 1191e69d4d44SBarry Smith For the Schur complement preconditioner if J = ( A B ) 1192e69d4d44SBarry Smith ( C D ) 1193e69d4d44SBarry Smith the preconditioner is 1194e69d4d44SBarry Smith (I -B inv(A)) ( inv(A) 0 ) (I 0 ) 1195e69d4d44SBarry Smith (0 I ) ( 0 inv(S) ) (-C inv(A) I ) 1196edf189efSBarry Smith where the action of inv(A) is applied using the KSP solver with prefix -fieldsplit_0_. The action of 1197e69d4d44SBarry Smith inv(S) is computed using the KSP solver with prefix -schur_. For PCFieldSplitGetKSP() when field number is 1198edf189efSBarry Smith 0 it returns the KSP associated with -fieldsplit_0_ while field number 1 gives -fieldsplit_1_ KSP. By default 1199e69d4d44SBarry Smith D is used to construct a preconditioner for S, use PCFieldSplitSchurPrecondition() to turn on or off this 1200e69d4d44SBarry Smith option. 1201e69d4d44SBarry Smith 1202edf189efSBarry Smith If only one set of indices (one IS) is provided with PCFieldSplitSetIS() then the complement of that IS 1203edf189efSBarry Smith is used automatically for a second block. 1204edf189efSBarry Smith 1205a541d17aSBarry Smith Concepts: physics based preconditioners, block preconditioners 12060971522cSBarry Smith 1207a541d17aSBarry Smith .seealso: PCCreate(), PCSetType(), PCType (for list of available types), PC, Block_Preconditioners 1208e69d4d44SBarry Smith PCFieldSplitGetSubKSP(), PCFieldSplitSetFields(), PCFieldSplitSetType(), PCFieldSplitSetIS(), PCFieldSplitSchurPrecondition() 12090971522cSBarry Smith M*/ 12100971522cSBarry Smith 12110971522cSBarry Smith EXTERN_C_BEGIN 12120971522cSBarry Smith #undef __FUNCT__ 12130971522cSBarry Smith #define __FUNCT__ "PCCreate_FieldSplit" 1214dba47a55SKris Buschelman PetscErrorCode PETSCKSP_DLLEXPORT PCCreate_FieldSplit(PC pc) 12150971522cSBarry Smith { 12160971522cSBarry Smith PetscErrorCode ierr; 12170971522cSBarry Smith PC_FieldSplit *jac; 12180971522cSBarry Smith 12190971522cSBarry Smith PetscFunctionBegin; 122038f2d2fdSLisandro Dalcin ierr = PetscNewLog(pc,PC_FieldSplit,&jac);CHKERRQ(ierr); 12210971522cSBarry Smith jac->bs = -1; 12220971522cSBarry Smith jac->nsplits = 0; 12233e197d65SBarry Smith jac->type = PC_COMPOSITE_MULTIPLICATIVE; 1224e6cab6aaSJed Brown jac->schurpre = PC_FIELDSPLIT_SCHUR_PRE_USER; /* Try user preconditioner first, fall back on diagonal */ 122551f519a2SBarry Smith 12260971522cSBarry Smith pc->data = (void*)jac; 12270971522cSBarry Smith 12280971522cSBarry Smith pc->ops->apply = PCApply_FieldSplit; 1229421e10b8SBarry Smith pc->ops->applytranspose = PCApplyTranspose_FieldSplit; 12300971522cSBarry Smith pc->ops->setup = PCSetUp_FieldSplit; 12310971522cSBarry Smith pc->ops->destroy = PCDestroy_FieldSplit; 12320971522cSBarry Smith pc->ops->setfromoptions = PCSetFromOptions_FieldSplit; 12330971522cSBarry Smith pc->ops->view = PCView_FieldSplit; 12340971522cSBarry Smith pc->ops->applyrichardson = 0; 12350971522cSBarry Smith 123669a612a9SBarry Smith ierr = PetscObjectComposeFunctionDynamic((PetscObject)pc,"PCFieldSplitGetSubKSP_C","PCFieldSplitGetSubKSP_FieldSplit", 123769a612a9SBarry Smith PCFieldSplitGetSubKSP_FieldSplit);CHKERRQ(ierr); 12380971522cSBarry Smith ierr = PetscObjectComposeFunctionDynamic((PetscObject)pc,"PCFieldSplitSetFields_C","PCFieldSplitSetFields_FieldSplit", 12390971522cSBarry Smith PCFieldSplitSetFields_FieldSplit);CHKERRQ(ierr); 1240704ba839SBarry Smith ierr = PetscObjectComposeFunctionDynamic((PetscObject)pc,"PCFieldSplitSetIS_C","PCFieldSplitSetIS_FieldSplit", 1241704ba839SBarry Smith PCFieldSplitSetIS_FieldSplit);CHKERRQ(ierr); 124279416396SBarry Smith ierr = PetscObjectComposeFunctionDynamic((PetscObject)pc,"PCFieldSplitSetType_C","PCFieldSplitSetType_FieldSplit", 124379416396SBarry Smith PCFieldSplitSetType_FieldSplit);CHKERRQ(ierr); 124451f519a2SBarry Smith ierr = PetscObjectComposeFunctionDynamic((PetscObject)pc,"PCFieldSplitSetBlockSize_C","PCFieldSplitSetBlockSize_FieldSplit", 124551f519a2SBarry Smith PCFieldSplitSetBlockSize_FieldSplit);CHKERRQ(ierr); 12460971522cSBarry Smith PetscFunctionReturn(0); 12470971522cSBarry Smith } 12480971522cSBarry Smith EXTERN_C_END 12490971522cSBarry Smith 12500971522cSBarry Smith 1251a541d17aSBarry Smith /*MC 1252a541d17aSBarry Smith Block_Preconditioners - PETSc provides support for a variety of "block preconditioners", this provides an 1253a541d17aSBarry Smith overview of these methods. 1254a541d17aSBarry Smith 1255a541d17aSBarry Smith Consider the solution to ( A B ) (x_1) = (b_1) 1256a541d17aSBarry Smith ( C D ) (x_2) (b_2) 1257a541d17aSBarry Smith 1258a541d17aSBarry Smith Important special cases, the Stokes equation: C = B' and D = 0 (A B) (x_1) = (b_1) 1259a541d17aSBarry Smith B' 0) (x_2) (b_2) 1260a541d17aSBarry Smith 1261a541d17aSBarry Smith One of the goals of the PCFieldSplit preconditioner in PETSc is to provide a variety of preconditioners 1262a541d17aSBarry Smith for this block system. 1263a541d17aSBarry Smith 1264a541d17aSBarry Smith Consider an additional matrix (Ap Bp) 1265a541d17aSBarry Smith (Cp Dp) where some or all of the entries may be the same as 1266a541d17aSBarry Smith in the original matrix (for example Ap == A). 1267a541d17aSBarry Smith 1268a541d17aSBarry Smith In the following, A^ denotes the approximate application of the inverse of A, possibly using Ap in the 1269a541d17aSBarry Smith approximation. In PETSc this simply means one has called KSPSetOperators(ksp,A,Ap,...) or KSPSetOperators(ksp,Ap,Ap,...) 1270a541d17aSBarry Smith 1271a541d17aSBarry Smith Block Jacobi: x_1 = A^ b_1 1272a541d17aSBarry Smith x_2 = D^ b_2 1273a541d17aSBarry Smith 1274a541d17aSBarry Smith Lower block Gauss-Seidel: x_1 = A^ b_1 1275a541d17aSBarry Smith x_2 = D^ (b_2 - C x_1) variant x_2 = D^ (b_2 - Cp x_1) 1276a541d17aSBarry Smith 1277a541d17aSBarry Smith Symmetric Gauss-Seidel: x_1 = x_1 + A^(b_1 - A x_1 - B x_2) variant x_1 = x_1 + A^(b_1 - Ap x_1 - Bp x_2) 1278a541d17aSBarry Smith Interestingly this form is not actually a symmetric matrix, the symmetric version is 1279a541d17aSBarry Smith x_1 = A^(b_1 - B x_2) variant x_1 = A^(b_1 - Bp x_2) 1280a541d17aSBarry Smith 12810bc0a719SBarry Smith Level: intermediate 12820bc0a719SBarry Smith 1283a541d17aSBarry Smith .seealso: PCCreate(), PCSetType(), PCType (for list of available types), PC, PCFIELDSPLIT 1284a541d17aSBarry Smith PCFieldSplitGetSubKSP(), PCFieldSplitSetFields(), PCFieldSplitSetType(), PCFieldSplitSetIS(), PCFieldSplitSchurPrecondition() 1285a541d17aSBarry Smith M*/ 1286