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 = PetscViewerASCIIPushTab(viewer);CHKERRQ(ierr); 13912cae6f2SJed Brown if (jac->schur) { 14012cae6f2SJed Brown ierr = MatSchurComplementGetKSP(jac->schur,&ksp);CHKERRQ(ierr); 1413b224e63SBarry Smith ierr = KSPView(ksp,viewer);CHKERRQ(ierr); 14212cae6f2SJed Brown } else { 14312cae6f2SJed Brown ierr = PetscViewerASCIIPrintf(viewer," not yet available\n");CHKERRQ(ierr); 14412cae6f2SJed Brown } 1453b224e63SBarry Smith ierr = PetscViewerASCIIPopTab(viewer);CHKERRQ(ierr); 1463b224e63SBarry Smith ierr = PetscViewerASCIIPrintf(viewer,"KSP solver for S = D - C inv(A) B \n");CHKERRQ(ierr); 1473b224e63SBarry Smith ierr = PetscViewerASCIIPushTab(viewer);CHKERRQ(ierr); 14812cae6f2SJed Brown if (jac->kspschur) { 1493b224e63SBarry Smith ierr = KSPView(jac->kspschur,viewer);CHKERRQ(ierr); 15012cae6f2SJed Brown } else { 15112cae6f2SJed Brown ierr = PetscViewerASCIIPrintf(viewer," not yet available\n");CHKERRQ(ierr); 15212cae6f2SJed Brown } 1533b224e63SBarry Smith ierr = PetscViewerASCIIPopTab(viewer);CHKERRQ(ierr); 1543b224e63SBarry Smith ierr = PetscViewerASCIIPopTab(viewer);CHKERRQ(ierr); 1553b224e63SBarry Smith } else { 1563b224e63SBarry Smith SETERRQ1(PETSC_ERR_SUP,"Viewer type %s not supported for PCFieldSplit",((PetscObject)viewer)->type_name); 1573b224e63SBarry Smith } 1583b224e63SBarry Smith PetscFunctionReturn(0); 1593b224e63SBarry Smith } 1603b224e63SBarry Smith 1613b224e63SBarry Smith #undef __FUNCT__ 16269a612a9SBarry Smith #define __FUNCT__ "PCFieldSplitSetDefaults" 16369a612a9SBarry Smith static PetscErrorCode PCFieldSplitSetDefaults(PC pc) 1640971522cSBarry Smith { 1650971522cSBarry Smith PC_FieldSplit *jac = (PC_FieldSplit*)pc->data; 1660971522cSBarry Smith PetscErrorCode ierr; 1675a9f2f41SSatish Balay PC_FieldSplitLink ilink = jac->head; 168d32f9abdSBarry Smith PetscInt i = 0,*ifields,nfields; 169d32f9abdSBarry Smith PetscTruth flg = PETSC_FALSE,*fields,flg2; 170d32f9abdSBarry Smith char optionname[128]; 1710971522cSBarry Smith 1720971522cSBarry Smith PetscFunctionBegin; 173d32f9abdSBarry Smith if (!ilink) { 174d32f9abdSBarry Smith 175521d7252SBarry Smith if (jac->bs <= 0) { 176704ba839SBarry Smith if (pc->pmat) { 177521d7252SBarry Smith ierr = MatGetBlockSize(pc->pmat,&jac->bs);CHKERRQ(ierr); 178704ba839SBarry Smith } else { 179704ba839SBarry Smith jac->bs = 1; 180704ba839SBarry Smith } 181521d7252SBarry Smith } 182d32f9abdSBarry Smith 183d32f9abdSBarry Smith ierr = PetscOptionsGetTruth(((PetscObject)pc)->prefix,"-pc_fieldsplit_default",&flg,PETSC_NULL);CHKERRQ(ierr); 184d32f9abdSBarry Smith if (!flg) { 185d32f9abdSBarry Smith /* Allow user to set fields from command line, if bs was known at the time of PCSetFromOptions_FieldSplit() 186d32f9abdSBarry Smith then it is set there. This is not ideal because we should only have options set in XXSetFromOptions(). */ 187d32f9abdSBarry Smith flg = PETSC_TRUE; /* switched off automatically if user sets fields manually here */ 188d32f9abdSBarry Smith ierr = PetscMalloc(jac->bs*sizeof(PetscInt),&ifields);CHKERRQ(ierr); 189d32f9abdSBarry Smith while (PETSC_TRUE) { 190d32f9abdSBarry Smith sprintf(optionname,"-pc_fieldsplit_%d_fields",(int)i++); 191d32f9abdSBarry Smith nfields = jac->bs; 192d32f9abdSBarry Smith ierr = PetscOptionsGetIntArray(((PetscObject)pc)->prefix,optionname,ifields,&nfields,&flg2);CHKERRQ(ierr); 193d32f9abdSBarry Smith if (!flg2) break; 194d32f9abdSBarry Smith if (!nfields) SETERRQ(PETSC_ERR_USER,"Cannot list zero fields"); 195d32f9abdSBarry Smith flg = PETSC_FALSE; 196d32f9abdSBarry Smith ierr = PCFieldSplitSetFields(pc,nfields,ifields);CHKERRQ(ierr); 197d32f9abdSBarry Smith } 198d32f9abdSBarry Smith ierr = PetscFree(ifields);CHKERRQ(ierr); 199d32f9abdSBarry Smith } 200d32f9abdSBarry Smith 201d32f9abdSBarry Smith if (flg) { 202d32f9abdSBarry Smith ierr = PetscInfo(pc,"Using default splitting of fields\n");CHKERRQ(ierr); 20379416396SBarry Smith ierr = PetscMalloc(jac->bs*sizeof(PetscTruth),&fields);CHKERRQ(ierr); 20479416396SBarry Smith ierr = PetscMemzero(fields,jac->bs*sizeof(PetscTruth));CHKERRQ(ierr); 2055a9f2f41SSatish Balay while (ilink) { 2065a9f2f41SSatish Balay for (i=0; i<ilink->nfields; i++) { 2075a9f2f41SSatish Balay fields[ilink->fields[i]] = PETSC_TRUE; 208521d7252SBarry Smith } 2095a9f2f41SSatish Balay ilink = ilink->next; 21079416396SBarry Smith } 21197bbdb24SBarry Smith jac->defaultsplit = PETSC_TRUE; 21279416396SBarry Smith for (i=0; i<jac->bs; i++) { 21379416396SBarry Smith if (!fields[i]) { 21479416396SBarry Smith ierr = PCFieldSplitSetFields(pc,1,&i);CHKERRQ(ierr); 21579416396SBarry Smith } else { 21679416396SBarry Smith jac->defaultsplit = PETSC_FALSE; 21779416396SBarry Smith } 21879416396SBarry Smith } 21968dd23aaSBarry Smith ierr = PetscFree(fields);CHKERRQ(ierr); 220521d7252SBarry Smith } 221edf189efSBarry Smith } else if (jac->nsplits == 1) { 222edf189efSBarry Smith if (ilink->is) { 223edf189efSBarry Smith IS is2; 224edf189efSBarry Smith PetscInt nmin,nmax; 225edf189efSBarry Smith 226edf189efSBarry Smith ierr = MatGetOwnershipRange(pc->mat,&nmin,&nmax);CHKERRQ(ierr); 227edf189efSBarry Smith ierr = ISComplement(ilink->is,nmin,nmax,&is2);CHKERRQ(ierr); 228edf189efSBarry Smith ierr = PCFieldSplitSetIS(pc,is2);CHKERRQ(ierr); 229edf189efSBarry Smith ierr = ISDestroy(is2);CHKERRQ(ierr); 230edf189efSBarry Smith } else { 231edf189efSBarry Smith SETERRQ(PETSC_ERR_SUP,"Must provide at least two sets of fields to PCFieldSplit()"); 232edf189efSBarry Smith } 233d32f9abdSBarry Smith } 234829b6ff0SJed Brown if (jac->nsplits < 2) { 235829b6ff0SJed Brown SETERRQ(PETSC_ERR_PLIB,"Unhandled case, must have at least two fields"); 236829b6ff0SJed Brown } 23769a612a9SBarry Smith PetscFunctionReturn(0); 23869a612a9SBarry Smith } 23969a612a9SBarry Smith 24069a612a9SBarry Smith 24169a612a9SBarry Smith #undef __FUNCT__ 24269a612a9SBarry Smith #define __FUNCT__ "PCSetUp_FieldSplit" 24369a612a9SBarry Smith static PetscErrorCode PCSetUp_FieldSplit(PC pc) 24469a612a9SBarry Smith { 24569a612a9SBarry Smith PC_FieldSplit *jac = (PC_FieldSplit*)pc->data; 24669a612a9SBarry Smith PetscErrorCode ierr; 2475a9f2f41SSatish Balay PC_FieldSplitLink ilink; 248cf502942SBarry Smith PetscInt i,nsplit,ccsize; 24969a612a9SBarry Smith MatStructure flag = pc->flag; 2506c8605c2SJed Brown PetscTruth sorted; 25169a612a9SBarry Smith 25269a612a9SBarry Smith PetscFunctionBegin; 25369a612a9SBarry Smith ierr = PCFieldSplitSetDefaults(pc);CHKERRQ(ierr); 25497bbdb24SBarry Smith nsplit = jac->nsplits; 2555a9f2f41SSatish Balay ilink = jac->head; 25697bbdb24SBarry Smith 25797bbdb24SBarry Smith /* get the matrices for each split */ 258704ba839SBarry Smith if (!jac->issetup) { 2591b9fc7fcSBarry Smith PetscInt rstart,rend,nslots,bs; 26097bbdb24SBarry Smith 261704ba839SBarry Smith jac->issetup = PETSC_TRUE; 262704ba839SBarry Smith 263704ba839SBarry Smith /* This is done here instead of in PCFieldSplitSetFields() because may not have matrix at that point */ 26451f519a2SBarry Smith bs = jac->bs; 26597bbdb24SBarry Smith ierr = MatGetOwnershipRange(pc->pmat,&rstart,&rend);CHKERRQ(ierr); 266cf502942SBarry Smith ierr = MatGetLocalSize(pc->pmat,PETSC_NULL,&ccsize);CHKERRQ(ierr); 2671b9fc7fcSBarry Smith nslots = (rend - rstart)/bs; 2681b9fc7fcSBarry Smith for (i=0; i<nsplit; i++) { 2691b9fc7fcSBarry Smith if (jac->defaultsplit) { 270704ba839SBarry Smith ierr = ISCreateStride(((PetscObject)pc)->comm,nslots,rstart+i,nsplit,&ilink->is);CHKERRQ(ierr); 271704ba839SBarry Smith } else if (!ilink->is) { 272ccb205f8SBarry Smith if (ilink->nfields > 1) { 2735a9f2f41SSatish Balay PetscInt *ii,j,k,nfields = ilink->nfields,*fields = ilink->fields; 2745a9f2f41SSatish Balay ierr = PetscMalloc(ilink->nfields*nslots*sizeof(PetscInt),&ii);CHKERRQ(ierr); 2751b9fc7fcSBarry Smith for (j=0; j<nslots; j++) { 2761b9fc7fcSBarry Smith for (k=0; k<nfields; k++) { 2771b9fc7fcSBarry Smith ii[nfields*j + k] = rstart + bs*j + fields[k]; 27897bbdb24SBarry Smith } 27997bbdb24SBarry Smith } 280704ba839SBarry Smith ierr = ISCreateGeneral(((PetscObject)pc)->comm,nslots*nfields,ii,&ilink->is);CHKERRQ(ierr); 281ccb205f8SBarry Smith ierr = PetscFree(ii);CHKERRQ(ierr); 282ccb205f8SBarry Smith } else { 283704ba839SBarry Smith ierr = ISCreateStride(((PetscObject)pc)->comm,nslots,rstart+ilink->fields[0],bs,&ilink->is);CHKERRQ(ierr); 284ccb205f8SBarry Smith } 2853e197d65SBarry Smith } 286704ba839SBarry Smith ierr = ISSorted(ilink->is,&sorted);CHKERRQ(ierr); 2871b9fc7fcSBarry Smith if (!sorted) SETERRQ(PETSC_ERR_USER,"Fields must be sorted when creating split"); 288704ba839SBarry Smith ilink = ilink->next; 2891b9fc7fcSBarry Smith } 2901b9fc7fcSBarry Smith } 2911b9fc7fcSBarry Smith 292704ba839SBarry Smith ilink = jac->head; 29397bbdb24SBarry Smith if (!jac->pmat) { 294cf502942SBarry Smith ierr = PetscMalloc(nsplit*sizeof(Mat),&jac->pmat);CHKERRQ(ierr); 295cf502942SBarry Smith for (i=0; i<nsplit; i++) { 2964aa3045dSJed Brown ierr = MatGetSubMatrix(pc->pmat,ilink->is,ilink->is,MAT_INITIAL_MATRIX,&jac->pmat[i]);CHKERRQ(ierr); 297704ba839SBarry Smith ilink = ilink->next; 298cf502942SBarry Smith } 29997bbdb24SBarry Smith } else { 300cf502942SBarry Smith for (i=0; i<nsplit; i++) { 3014aa3045dSJed Brown ierr = MatGetSubMatrix(pc->pmat,ilink->is,ilink->is,MAT_REUSE_MATRIX,&jac->pmat[i]);CHKERRQ(ierr); 302704ba839SBarry Smith ilink = ilink->next; 303cf502942SBarry Smith } 30497bbdb24SBarry Smith } 305519d70e2SJed Brown if (jac->realdiagonal) { 306519d70e2SJed Brown ilink = jac->head; 307519d70e2SJed Brown if (!jac->mat) { 308519d70e2SJed Brown ierr = PetscMalloc(nsplit*sizeof(Mat),&jac->mat);CHKERRQ(ierr); 309519d70e2SJed Brown for (i=0; i<nsplit; i++) { 310519d70e2SJed Brown ierr = MatGetSubMatrix(pc->mat,ilink->is,ilink->is,MAT_INITIAL_MATRIX,&jac->mat[i]);CHKERRQ(ierr); 311519d70e2SJed Brown ilink = ilink->next; 312519d70e2SJed Brown } 313519d70e2SJed Brown } else { 314519d70e2SJed Brown for (i=0; i<nsplit; i++) { 315519d70e2SJed Brown ierr = MatGetSubMatrix(pc->mat,ilink->is,ilink->is,MAT_REUSE_MATRIX,&jac->mat[i]);CHKERRQ(ierr); 316519d70e2SJed Brown ilink = ilink->next; 317519d70e2SJed Brown } 318519d70e2SJed Brown } 319519d70e2SJed Brown } else { 320519d70e2SJed Brown jac->mat = jac->pmat; 321519d70e2SJed Brown } 32297bbdb24SBarry Smith 3236c8605c2SJed Brown if (jac->type != PC_COMPOSITE_ADDITIVE && jac->type != PC_COMPOSITE_SCHUR) { 32468dd23aaSBarry Smith /* extract the rows of the matrix associated with each field: used for efficient computation of residual inside algorithm */ 32568dd23aaSBarry Smith ilink = jac->head; 32668dd23aaSBarry Smith if (!jac->Afield) { 32768dd23aaSBarry Smith ierr = PetscMalloc(nsplit*sizeof(Mat),&jac->Afield);CHKERRQ(ierr); 32868dd23aaSBarry Smith for (i=0; i<nsplit; i++) { 3294aa3045dSJed Brown ierr = MatGetSubMatrix(pc->mat,ilink->is,PETSC_NULL,MAT_INITIAL_MATRIX,&jac->Afield[i]);CHKERRQ(ierr); 33068dd23aaSBarry Smith ilink = ilink->next; 33168dd23aaSBarry Smith } 33268dd23aaSBarry Smith } else { 33368dd23aaSBarry Smith for (i=0; i<nsplit; i++) { 3344aa3045dSJed Brown ierr = MatGetSubMatrix(pc->mat,ilink->is,PETSC_NULL,MAT_REUSE_MATRIX,&jac->Afield[i]);CHKERRQ(ierr); 33568dd23aaSBarry Smith ilink = ilink->next; 33668dd23aaSBarry Smith } 33768dd23aaSBarry Smith } 33868dd23aaSBarry Smith } 33968dd23aaSBarry Smith 3403b224e63SBarry Smith if (jac->type == PC_COMPOSITE_SCHUR) { 3413b224e63SBarry Smith IS ccis; 3424aa3045dSJed Brown PetscInt rstart,rend; 3433b224e63SBarry Smith if (nsplit != 2) SETERRQ(PETSC_ERR_ARG_INCOMP,"To use Schur complement preconditioner you must have exactly 2 fields"); 34468dd23aaSBarry Smith 345e6cab6aaSJed Brown /* When extracting off-diagonal submatrices, we take complements from this range */ 346e6cab6aaSJed Brown ierr = MatGetOwnershipRangeColumn(pc->mat,&rstart,&rend);CHKERRQ(ierr); 347e6cab6aaSJed Brown 3483b224e63SBarry Smith /* need to handle case when one is resetting up the preconditioner */ 3493b224e63SBarry Smith if (jac->schur) { 3503b224e63SBarry Smith ilink = jac->head; 3514aa3045dSJed Brown ierr = ISComplement(ilink->is,rstart,rend,&ccis);CHKERRQ(ierr); 3524aa3045dSJed Brown ierr = MatGetSubMatrix(pc->mat,ilink->is,ccis,MAT_REUSE_MATRIX,&jac->B);CHKERRQ(ierr); 3533b224e63SBarry Smith ierr = ISDestroy(ccis);CHKERRQ(ierr); 3543b224e63SBarry Smith ilink = ilink->next; 3554aa3045dSJed Brown ierr = ISComplement(ilink->is,rstart,rend,&ccis);CHKERRQ(ierr); 3564aa3045dSJed Brown ierr = MatGetSubMatrix(pc->mat,ilink->is,ccis,MAT_REUSE_MATRIX,&jac->C);CHKERRQ(ierr); 3573b224e63SBarry Smith ierr = ISDestroy(ccis);CHKERRQ(ierr); 358519d70e2SJed Brown ierr = MatSchurComplementUpdate(jac->schur,jac->mat[0],jac->pmat[0],jac->B,jac->C,jac->pmat[1],pc->flag);CHKERRQ(ierr); 359084e4875SJed Brown ierr = KSPSetOperators(jac->kspschur,jac->schur,FieldSplitSchurPre(jac),pc->flag);CHKERRQ(ierr); 3603b224e63SBarry Smith 3613b224e63SBarry Smith } else { 3621cee3971SBarry Smith KSP ksp; 3633b224e63SBarry Smith 3643b224e63SBarry Smith /* extract the B and C matrices */ 3653b224e63SBarry Smith ilink = jac->head; 3664aa3045dSJed Brown ierr = ISComplement(ilink->is,rstart,rend,&ccis);CHKERRQ(ierr); 3674aa3045dSJed Brown ierr = MatGetSubMatrix(pc->mat,ilink->is,ccis,MAT_INITIAL_MATRIX,&jac->B);CHKERRQ(ierr); 3683b224e63SBarry Smith ierr = ISDestroy(ccis);CHKERRQ(ierr); 3693b224e63SBarry Smith ilink = ilink->next; 3704aa3045dSJed Brown ierr = ISComplement(ilink->is,rstart,rend,&ccis);CHKERRQ(ierr); 3714aa3045dSJed Brown ierr = MatGetSubMatrix(pc->mat,ilink->is,ccis,MAT_INITIAL_MATRIX,&jac->C);CHKERRQ(ierr); 3723b224e63SBarry Smith ierr = ISDestroy(ccis);CHKERRQ(ierr); 373084e4875SJed Brown /* Better would be to use 'mat[0]' (diagonal block of the real matrix) preconditioned by pmat[0] */ 374519d70e2SJed Brown ierr = MatCreateSchurComplement(jac->mat[0],jac->pmat[0],jac->B,jac->C,jac->mat[1],&jac->schur);CHKERRQ(ierr); 3751cee3971SBarry Smith ierr = MatSchurComplementGetKSP(jac->schur,&ksp);CHKERRQ(ierr); 376e69d4d44SBarry Smith ierr = PetscObjectIncrementTabLevel((PetscObject)ksp,(PetscObject)pc,2);CHKERRQ(ierr); 3773b224e63SBarry Smith ierr = MatSetFromOptions(jac->schur);CHKERRQ(ierr); 3783b224e63SBarry Smith 3793b224e63SBarry Smith ierr = KSPCreate(((PetscObject)pc)->comm,&jac->kspschur);CHKERRQ(ierr); 3801cee3971SBarry Smith ierr = PetscObjectIncrementTabLevel((PetscObject)jac->kspschur,(PetscObject)pc,1);CHKERRQ(ierr); 381084e4875SJed Brown ierr = KSPSetOperators(jac->kspschur,jac->schur,FieldSplitSchurPre(jac),DIFFERENT_NONZERO_PATTERN);CHKERRQ(ierr); 382084e4875SJed Brown if (jac->schurpre == PC_FIELDSPLIT_SCHUR_PRE_SELF) { 383084e4875SJed Brown PC pc; 384cd5f4a64SJed Brown ierr = KSPGetPC(jac->kspschur,&pc);CHKERRQ(ierr); 385084e4875SJed Brown ierr = PCSetType(pc,PCNONE);CHKERRQ(ierr); 386084e4875SJed Brown /* Note: This is bad if there exist preconditioners for MATSCHURCOMPLEMENT */ 387e69d4d44SBarry Smith } 3883b224e63SBarry Smith ierr = KSPSetOptionsPrefix(jac->kspschur,((PetscObject)pc)->prefix);CHKERRQ(ierr); 389edf189efSBarry Smith ierr = KSPAppendOptionsPrefix(jac->kspschur,"fieldsplit_1_");CHKERRQ(ierr); 3903b224e63SBarry Smith /* really want setfromoptions called in PCSetFromOptions_FieldSplit(), but it is not ready yet */ 3913b224e63SBarry Smith ierr = KSPSetFromOptions(jac->kspschur);CHKERRQ(ierr); 3923b224e63SBarry Smith 3933b224e63SBarry Smith ierr = PetscMalloc2(2,Vec,&jac->x,2,Vec,&jac->y);CHKERRQ(ierr); 3943b224e63SBarry Smith ierr = MatGetVecs(jac->pmat[0],&jac->x[0],&jac->y[0]);CHKERRQ(ierr); 3953b224e63SBarry Smith ierr = MatGetVecs(jac->pmat[1],&jac->x[1],&jac->y[1]);CHKERRQ(ierr); 3963b224e63SBarry Smith ilink = jac->head; 3973b224e63SBarry Smith ilink->x = jac->x[0]; ilink->y = jac->y[0]; 3983b224e63SBarry Smith ilink = ilink->next; 3993b224e63SBarry Smith ilink->x = jac->x[1]; ilink->y = jac->y[1]; 4003b224e63SBarry Smith } 4013b224e63SBarry Smith } else { 40297bbdb24SBarry Smith /* set up the individual PCs */ 40397bbdb24SBarry Smith i = 0; 4045a9f2f41SSatish Balay ilink = jac->head; 4055a9f2f41SSatish Balay while (ilink) { 406519d70e2SJed Brown ierr = KSPSetOperators(ilink->ksp,jac->mat[i],jac->pmat[i],flag);CHKERRQ(ierr); 4073b224e63SBarry Smith /* really want setfromoptions called in PCSetFromOptions_FieldSplit(), but it is not ready yet */ 4085a9f2f41SSatish Balay ierr = KSPSetFromOptions(ilink->ksp);CHKERRQ(ierr); 4095a9f2f41SSatish Balay ierr = KSPSetUp(ilink->ksp);CHKERRQ(ierr); 41097bbdb24SBarry Smith i++; 4115a9f2f41SSatish Balay ilink = ilink->next; 4120971522cSBarry Smith } 41397bbdb24SBarry Smith 41497bbdb24SBarry Smith /* create work vectors for each split */ 4151b9fc7fcSBarry Smith if (!jac->x) { 41697bbdb24SBarry Smith ierr = PetscMalloc2(nsplit,Vec,&jac->x,nsplit,Vec,&jac->y);CHKERRQ(ierr); 4175a9f2f41SSatish Balay ilink = jac->head; 41897bbdb24SBarry Smith for (i=0; i<nsplit; i++) { 419906ed7ccSBarry Smith Vec *vl,*vr; 420906ed7ccSBarry Smith 421906ed7ccSBarry Smith ierr = KSPGetVecs(ilink->ksp,1,&vr,1,&vl);CHKERRQ(ierr); 422906ed7ccSBarry Smith ilink->x = *vr; 423906ed7ccSBarry Smith ilink->y = *vl; 424906ed7ccSBarry Smith ierr = PetscFree(vr);CHKERRQ(ierr); 425906ed7ccSBarry Smith ierr = PetscFree(vl);CHKERRQ(ierr); 4265a9f2f41SSatish Balay jac->x[i] = ilink->x; 4275a9f2f41SSatish Balay jac->y[i] = ilink->y; 4285a9f2f41SSatish Balay ilink = ilink->next; 42997bbdb24SBarry Smith } 4303b224e63SBarry Smith } 4313b224e63SBarry Smith } 4323b224e63SBarry Smith 4333b224e63SBarry Smith 434d0f46423SBarry Smith if (!jac->head->sctx) { 4353b224e63SBarry Smith Vec xtmp; 4363b224e63SBarry Smith 43779416396SBarry Smith /* compute scatter contexts needed by multiplicative versions and non-default splits */ 4381b9fc7fcSBarry Smith 4395a9f2f41SSatish Balay ilink = jac->head; 4401b9fc7fcSBarry Smith ierr = MatGetVecs(pc->pmat,&xtmp,PETSC_NULL);CHKERRQ(ierr); 4411b9fc7fcSBarry Smith for (i=0; i<nsplit; i++) { 442704ba839SBarry Smith ierr = VecScatterCreate(xtmp,ilink->is,jac->x[i],PETSC_NULL,&ilink->sctx);CHKERRQ(ierr); 4435a9f2f41SSatish Balay ilink = ilink->next; 4441b9fc7fcSBarry Smith } 4451b9fc7fcSBarry Smith ierr = VecDestroy(xtmp);CHKERRQ(ierr); 4461b9fc7fcSBarry Smith } 4470971522cSBarry Smith PetscFunctionReturn(0); 4480971522cSBarry Smith } 4490971522cSBarry Smith 4505a9f2f41SSatish Balay #define FieldSplitSplitSolveAdd(ilink,xx,yy) \ 451ca9f406cSSatish Balay (VecScatterBegin(ilink->sctx,xx,ilink->x,INSERT_VALUES,SCATTER_FORWARD) || \ 452ca9f406cSSatish Balay VecScatterEnd(ilink->sctx,xx,ilink->x,INSERT_VALUES,SCATTER_FORWARD) || \ 4535a9f2f41SSatish Balay KSPSolve(ilink->ksp,ilink->x,ilink->y) || \ 454ca9f406cSSatish Balay VecScatterBegin(ilink->sctx,ilink->y,yy,ADD_VALUES,SCATTER_REVERSE) || \ 455ca9f406cSSatish Balay VecScatterEnd(ilink->sctx,ilink->y,yy,ADD_VALUES,SCATTER_REVERSE)) 45679416396SBarry Smith 4570971522cSBarry Smith #undef __FUNCT__ 4583b224e63SBarry Smith #define __FUNCT__ "PCApply_FieldSplit_Schur" 4593b224e63SBarry Smith static PetscErrorCode PCApply_FieldSplit_Schur(PC pc,Vec x,Vec y) 4603b224e63SBarry Smith { 4613b224e63SBarry Smith PC_FieldSplit *jac = (PC_FieldSplit*)pc->data; 4623b224e63SBarry Smith PetscErrorCode ierr; 4633b224e63SBarry Smith KSP ksp; 4643b224e63SBarry Smith PC_FieldSplitLink ilinkA = jac->head, ilinkD = ilinkA->next; 4653b224e63SBarry Smith 4663b224e63SBarry Smith PetscFunctionBegin; 4673b224e63SBarry Smith ierr = MatSchurComplementGetKSP(jac->schur,&ksp);CHKERRQ(ierr); 4683b224e63SBarry Smith 4693b224e63SBarry Smith ierr = VecScatterBegin(ilinkA->sctx,x,ilinkA->x,INSERT_VALUES,SCATTER_FORWARD);CHKERRQ(ierr); 4703b224e63SBarry Smith ierr = VecScatterEnd(ilinkA->sctx,x,ilinkA->x,INSERT_VALUES,SCATTER_FORWARD);CHKERRQ(ierr); 4713b224e63SBarry Smith ierr = KSPSolve(ksp,ilinkA->x,ilinkA->y);CHKERRQ(ierr); 4723b224e63SBarry Smith ierr = MatMult(jac->C,ilinkA->y,ilinkD->x);CHKERRQ(ierr); 4733b224e63SBarry Smith ierr = VecScale(ilinkD->x,-1.0);CHKERRQ(ierr); 4743b224e63SBarry Smith ierr = VecScatterBegin(ilinkD->sctx,x,ilinkD->x,ADD_VALUES,SCATTER_FORWARD);CHKERRQ(ierr); 4753b224e63SBarry Smith ierr = VecScatterEnd(ilinkD->sctx,x,ilinkD->x,ADD_VALUES,SCATTER_FORWARD);CHKERRQ(ierr); 4763b224e63SBarry Smith 4773b224e63SBarry Smith ierr = KSPSolve(jac->kspschur,ilinkD->x,ilinkD->y);CHKERRQ(ierr); 4783b224e63SBarry Smith ierr = VecScatterBegin(ilinkD->sctx,ilinkD->y,y,INSERT_VALUES,SCATTER_REVERSE);CHKERRQ(ierr); 4793b224e63SBarry Smith ierr = VecScatterEnd(ilinkD->sctx,ilinkD->y,y,INSERT_VALUES,SCATTER_REVERSE);CHKERRQ(ierr); 4803b224e63SBarry Smith 4813b224e63SBarry Smith ierr = MatMult(jac->B,ilinkD->y,ilinkA->y);CHKERRQ(ierr); 4823b224e63SBarry Smith ierr = VecAXPY(ilinkA->x,-1.0,ilinkA->y);CHKERRQ(ierr); 4833b224e63SBarry Smith ierr = KSPSolve(ksp,ilinkA->x,ilinkA->y);CHKERRQ(ierr); 4843b224e63SBarry Smith ierr = VecScatterBegin(ilinkA->sctx,ilinkA->y,y,INSERT_VALUES,SCATTER_REVERSE);CHKERRQ(ierr); 4853b224e63SBarry Smith ierr = VecScatterEnd(ilinkA->sctx,ilinkA->y,y,INSERT_VALUES,SCATTER_REVERSE);CHKERRQ(ierr); 4863b224e63SBarry Smith 4873b224e63SBarry Smith PetscFunctionReturn(0); 4883b224e63SBarry Smith } 4893b224e63SBarry Smith 4903b224e63SBarry Smith #undef __FUNCT__ 4910971522cSBarry Smith #define __FUNCT__ "PCApply_FieldSplit" 4920971522cSBarry Smith static PetscErrorCode PCApply_FieldSplit(PC pc,Vec x,Vec y) 4930971522cSBarry Smith { 4940971522cSBarry Smith PC_FieldSplit *jac = (PC_FieldSplit*)pc->data; 4950971522cSBarry Smith PetscErrorCode ierr; 4965a9f2f41SSatish Balay PC_FieldSplitLink ilink = jac->head; 497af93645bSJed Brown PetscInt cnt; 4980971522cSBarry Smith 4990971522cSBarry Smith PetscFunctionBegin; 50051f519a2SBarry Smith CHKMEMQ; 50151f519a2SBarry Smith ierr = VecSetBlockSize(x,jac->bs);CHKERRQ(ierr); 50251f519a2SBarry Smith ierr = VecSetBlockSize(y,jac->bs);CHKERRQ(ierr); 50351f519a2SBarry Smith 50479416396SBarry Smith if (jac->type == PC_COMPOSITE_ADDITIVE) { 5051b9fc7fcSBarry Smith if (jac->defaultsplit) { 5060971522cSBarry Smith ierr = VecStrideGatherAll(x,jac->x,INSERT_VALUES);CHKERRQ(ierr); 5075a9f2f41SSatish Balay while (ilink) { 5085a9f2f41SSatish Balay ierr = KSPSolve(ilink->ksp,ilink->x,ilink->y);CHKERRQ(ierr); 5095a9f2f41SSatish Balay ilink = ilink->next; 5100971522cSBarry Smith } 5110971522cSBarry Smith ierr = VecStrideScatterAll(jac->y,y,INSERT_VALUES);CHKERRQ(ierr); 5121b9fc7fcSBarry Smith } else { 513efb30889SBarry Smith ierr = VecSet(y,0.0);CHKERRQ(ierr); 5145a9f2f41SSatish Balay while (ilink) { 5155a9f2f41SSatish Balay ierr = FieldSplitSplitSolveAdd(ilink,x,y);CHKERRQ(ierr); 5165a9f2f41SSatish Balay ilink = ilink->next; 5171b9fc7fcSBarry Smith } 5181b9fc7fcSBarry Smith } 51916913363SBarry Smith } else if (jac->type == PC_COMPOSITE_MULTIPLICATIVE || jac->type == PC_COMPOSITE_SYMMETRIC_MULTIPLICATIVE) { 52079416396SBarry Smith if (!jac->w1) { 52179416396SBarry Smith ierr = VecDuplicate(x,&jac->w1);CHKERRQ(ierr); 52279416396SBarry Smith ierr = VecDuplicate(x,&jac->w2);CHKERRQ(ierr); 52379416396SBarry Smith } 524efb30889SBarry Smith ierr = VecSet(y,0.0);CHKERRQ(ierr); 5255a9f2f41SSatish Balay ierr = FieldSplitSplitSolveAdd(ilink,x,y);CHKERRQ(ierr); 5263e197d65SBarry Smith cnt = 1; 5275a9f2f41SSatish Balay while (ilink->next) { 5285a9f2f41SSatish Balay ilink = ilink->next; 5293e197d65SBarry Smith /* compute the residual only over the part of the vector needed */ 5303e197d65SBarry Smith ierr = MatMult(jac->Afield[cnt++],y,ilink->x);CHKERRQ(ierr); 5313e197d65SBarry Smith ierr = VecScale(ilink->x,-1.0);CHKERRQ(ierr); 5323e197d65SBarry Smith ierr = VecScatterBegin(ilink->sctx,x,ilink->x,ADD_VALUES,SCATTER_FORWARD);CHKERRQ(ierr); 5333e197d65SBarry Smith ierr = VecScatterEnd(ilink->sctx,x,ilink->x,ADD_VALUES,SCATTER_FORWARD);CHKERRQ(ierr); 5343e197d65SBarry Smith ierr = KSPSolve(ilink->ksp,ilink->x,ilink->y);CHKERRQ(ierr); 5353e197d65SBarry Smith ierr = VecScatterBegin(ilink->sctx,ilink->y,y,ADD_VALUES,SCATTER_REVERSE);CHKERRQ(ierr); 5363e197d65SBarry Smith ierr = VecScatterEnd(ilink->sctx,ilink->y,y,ADD_VALUES,SCATTER_REVERSE);CHKERRQ(ierr); 5373e197d65SBarry Smith } 53851f519a2SBarry Smith if (jac->type == PC_COMPOSITE_SYMMETRIC_MULTIPLICATIVE) { 53911755939SBarry Smith cnt -= 2; 54051f519a2SBarry Smith while (ilink->previous) { 54151f519a2SBarry Smith ilink = ilink->previous; 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); 55051f519a2SBarry Smith } 55111755939SBarry Smith } 55216913363SBarry Smith } else SETERRQ1(PETSC_ERR_SUP,"Unsupported or unknown composition",(int) jac->type); 55351f519a2SBarry Smith CHKMEMQ; 5540971522cSBarry Smith PetscFunctionReturn(0); 5550971522cSBarry Smith } 5560971522cSBarry Smith 557421e10b8SBarry Smith #define FieldSplitSplitSolveAddTranspose(ilink,xx,yy) \ 558ca9f406cSSatish Balay (VecScatterBegin(ilink->sctx,xx,ilink->y,INSERT_VALUES,SCATTER_FORWARD) || \ 559ca9f406cSSatish Balay VecScatterEnd(ilink->sctx,xx,ilink->y,INSERT_VALUES,SCATTER_FORWARD) || \ 560421e10b8SBarry Smith KSPSolveTranspose(ilink->ksp,ilink->y,ilink->x) || \ 561ca9f406cSSatish Balay VecScatterBegin(ilink->sctx,ilink->x,yy,ADD_VALUES,SCATTER_REVERSE) || \ 562ca9f406cSSatish Balay VecScatterEnd(ilink->sctx,ilink->x,yy,ADD_VALUES,SCATTER_REVERSE)) 563421e10b8SBarry Smith 564421e10b8SBarry Smith #undef __FUNCT__ 565421e10b8SBarry Smith #define __FUNCT__ "PCApply_FieldSplit" 566421e10b8SBarry Smith static PetscErrorCode PCApplyTranspose_FieldSplit(PC pc,Vec x,Vec y) 567421e10b8SBarry Smith { 568421e10b8SBarry Smith PC_FieldSplit *jac = (PC_FieldSplit*)pc->data; 569421e10b8SBarry Smith PetscErrorCode ierr; 570421e10b8SBarry Smith PC_FieldSplitLink ilink = jac->head; 571421e10b8SBarry Smith 572421e10b8SBarry Smith PetscFunctionBegin; 573421e10b8SBarry Smith CHKMEMQ; 574421e10b8SBarry Smith ierr = VecSetBlockSize(x,jac->bs);CHKERRQ(ierr); 575421e10b8SBarry Smith ierr = VecSetBlockSize(y,jac->bs);CHKERRQ(ierr); 576421e10b8SBarry Smith 577421e10b8SBarry Smith if (jac->type == PC_COMPOSITE_ADDITIVE) { 578421e10b8SBarry Smith if (jac->defaultsplit) { 579421e10b8SBarry Smith ierr = VecStrideGatherAll(x,jac->x,INSERT_VALUES);CHKERRQ(ierr); 580421e10b8SBarry Smith while (ilink) { 581421e10b8SBarry Smith ierr = KSPSolveTranspose(ilink->ksp,ilink->x,ilink->y);CHKERRQ(ierr); 582421e10b8SBarry Smith ilink = ilink->next; 583421e10b8SBarry Smith } 584421e10b8SBarry Smith ierr = VecStrideScatterAll(jac->y,y,INSERT_VALUES);CHKERRQ(ierr); 585421e10b8SBarry Smith } else { 586421e10b8SBarry Smith ierr = VecSet(y,0.0);CHKERRQ(ierr); 587421e10b8SBarry Smith while (ilink) { 588421e10b8SBarry Smith ierr = FieldSplitSplitSolveAddTranspose(ilink,x,y);CHKERRQ(ierr); 589421e10b8SBarry Smith ilink = ilink->next; 590421e10b8SBarry Smith } 591421e10b8SBarry Smith } 592421e10b8SBarry Smith } else { 593421e10b8SBarry Smith if (!jac->w1) { 594421e10b8SBarry Smith ierr = VecDuplicate(x,&jac->w1);CHKERRQ(ierr); 595421e10b8SBarry Smith ierr = VecDuplicate(x,&jac->w2);CHKERRQ(ierr); 596421e10b8SBarry Smith } 597421e10b8SBarry Smith ierr = VecSet(y,0.0);CHKERRQ(ierr); 598421e10b8SBarry Smith if (jac->type == PC_COMPOSITE_SYMMETRIC_MULTIPLICATIVE) { 599421e10b8SBarry Smith ierr = FieldSplitSplitSolveAddTranspose(ilink,x,y);CHKERRQ(ierr); 600421e10b8SBarry Smith while (ilink->next) { 601421e10b8SBarry Smith ilink = ilink->next; 6029989ab13SBarry Smith ierr = MatMultTranspose(pc->mat,y,jac->w1);CHKERRQ(ierr); 603421e10b8SBarry Smith ierr = VecWAXPY(jac->w2,-1.0,jac->w1,x);CHKERRQ(ierr); 604421e10b8SBarry Smith ierr = FieldSplitSplitSolveAddTranspose(ilink,jac->w2,y);CHKERRQ(ierr); 605421e10b8SBarry Smith } 606421e10b8SBarry Smith while (ilink->previous) { 607421e10b8SBarry Smith ilink = ilink->previous; 6089989ab13SBarry Smith ierr = MatMultTranspose(pc->mat,y,jac->w1);CHKERRQ(ierr); 609421e10b8SBarry Smith ierr = VecWAXPY(jac->w2,-1.0,jac->w1,x);CHKERRQ(ierr); 610421e10b8SBarry Smith ierr = FieldSplitSplitSolveAddTranspose(ilink,jac->w2,y);CHKERRQ(ierr); 611421e10b8SBarry Smith } 612421e10b8SBarry Smith } else { 613421e10b8SBarry Smith while (ilink->next) { /* get to last entry in linked list */ 614421e10b8SBarry Smith ilink = ilink->next; 615421e10b8SBarry Smith } 616421e10b8SBarry Smith ierr = FieldSplitSplitSolveAddTranspose(ilink,x,y);CHKERRQ(ierr); 617421e10b8SBarry Smith while (ilink->previous) { 618421e10b8SBarry Smith ilink = ilink->previous; 6199989ab13SBarry Smith ierr = MatMultTranspose(pc->mat,y,jac->w1);CHKERRQ(ierr); 620421e10b8SBarry Smith ierr = VecWAXPY(jac->w2,-1.0,jac->w1,x);CHKERRQ(ierr); 621421e10b8SBarry Smith ierr = FieldSplitSplitSolveAddTranspose(ilink,jac->w2,y);CHKERRQ(ierr); 622421e10b8SBarry Smith } 623421e10b8SBarry Smith } 624421e10b8SBarry Smith } 625421e10b8SBarry Smith CHKMEMQ; 626421e10b8SBarry Smith PetscFunctionReturn(0); 627421e10b8SBarry Smith } 628421e10b8SBarry Smith 6290971522cSBarry Smith #undef __FUNCT__ 6300971522cSBarry Smith #define __FUNCT__ "PCDestroy_FieldSplit" 6310971522cSBarry Smith static PetscErrorCode PCDestroy_FieldSplit(PC pc) 6320971522cSBarry Smith { 6330971522cSBarry Smith PC_FieldSplit *jac = (PC_FieldSplit*)pc->data; 6340971522cSBarry Smith PetscErrorCode ierr; 6355a9f2f41SSatish Balay PC_FieldSplitLink ilink = jac->head,next; 6360971522cSBarry Smith 6370971522cSBarry Smith PetscFunctionBegin; 6385a9f2f41SSatish Balay while (ilink) { 6395a9f2f41SSatish Balay ierr = KSPDestroy(ilink->ksp);CHKERRQ(ierr); 6405a9f2f41SSatish Balay if (ilink->x) {ierr = VecDestroy(ilink->x);CHKERRQ(ierr);} 6415a9f2f41SSatish Balay if (ilink->y) {ierr = VecDestroy(ilink->y);CHKERRQ(ierr);} 6425a9f2f41SSatish Balay if (ilink->sctx) {ierr = VecScatterDestroy(ilink->sctx);CHKERRQ(ierr);} 643704ba839SBarry Smith if (ilink->is) {ierr = ISDestroy(ilink->is);CHKERRQ(ierr);} 6445a9f2f41SSatish Balay next = ilink->next; 645704ba839SBarry Smith ierr = PetscFree(ilink->fields);CHKERRQ(ierr); 646704ba839SBarry Smith ierr = PetscFree(ilink);CHKERRQ(ierr); 6475a9f2f41SSatish Balay ilink = next; 6480971522cSBarry Smith } 64905b42c5fSBarry Smith ierr = PetscFree2(jac->x,jac->y);CHKERRQ(ierr); 650519d70e2SJed Brown if (jac->mat && jac->mat != jac->pmat) {ierr = MatDestroyMatrices(jac->nsplits,&jac->mat);CHKERRQ(ierr);} 65197bbdb24SBarry Smith if (jac->pmat) {ierr = MatDestroyMatrices(jac->nsplits,&jac->pmat);CHKERRQ(ierr);} 65268dd23aaSBarry Smith if (jac->Afield) {ierr = MatDestroyMatrices(jac->nsplits,&jac->Afield);CHKERRQ(ierr);} 65379416396SBarry Smith if (jac->w1) {ierr = VecDestroy(jac->w1);CHKERRQ(ierr);} 65479416396SBarry Smith if (jac->w2) {ierr = VecDestroy(jac->w2);CHKERRQ(ierr);} 6553b224e63SBarry Smith if (jac->schur) {ierr = MatDestroy(jac->schur);CHKERRQ(ierr);} 656084e4875SJed Brown if (jac->schur_user) {ierr = MatDestroy(jac->schur_user);CHKERRQ(ierr);} 657d0f46423SBarry Smith if (jac->kspschur) {ierr = KSPDestroy(jac->kspschur);CHKERRQ(ierr);} 6583b224e63SBarry Smith if (jac->B) {ierr = MatDestroy(jac->B);CHKERRQ(ierr);} 6593b224e63SBarry Smith if (jac->C) {ierr = MatDestroy(jac->C);CHKERRQ(ierr);} 6600971522cSBarry Smith ierr = PetscFree(jac);CHKERRQ(ierr); 6610971522cSBarry Smith PetscFunctionReturn(0); 6620971522cSBarry Smith } 6630971522cSBarry Smith 6640971522cSBarry Smith #undef __FUNCT__ 6650971522cSBarry Smith #define __FUNCT__ "PCSetFromOptions_FieldSplit" 6660971522cSBarry Smith static PetscErrorCode PCSetFromOptions_FieldSplit(PC pc) 6670971522cSBarry Smith { 6681b9fc7fcSBarry Smith PetscErrorCode ierr; 66951f519a2SBarry Smith PetscInt i = 0,nfields,*fields,bs; 670084e4875SJed Brown PetscTruth flg; 6711b9fc7fcSBarry Smith char optionname[128]; 6729dcbbd2bSBarry Smith PC_FieldSplit *jac = (PC_FieldSplit*)pc->data; 6733b224e63SBarry Smith PCCompositeType ctype; 6741b9fc7fcSBarry Smith 6750971522cSBarry Smith PetscFunctionBegin; 6761b9fc7fcSBarry Smith ierr = PetscOptionsHead("FieldSplit options");CHKERRQ(ierr); 677519d70e2SJed Brown ierr = PetscOptionsTruth("-pc_fieldsplit_real_diagonal","Use diagonal blocks of the operator","PCFieldSplitSetRealDiagonal",jac->realdiagonal,&jac->realdiagonal,PETSC_NULL);CHKERRQ(ierr); 67851f519a2SBarry Smith ierr = PetscOptionsInt("-pc_fieldsplit_block_size","Blocksize that defines number of fields","PCFieldSplitSetBlockSize",jac->bs,&bs,&flg);CHKERRQ(ierr); 67951f519a2SBarry Smith if (flg) { 68051f519a2SBarry Smith ierr = PCFieldSplitSetBlockSize(pc,bs);CHKERRQ(ierr); 68151f519a2SBarry Smith } 682704ba839SBarry Smith 6833b224e63SBarry Smith ierr = PetscOptionsEnum("-pc_fieldsplit_type","Type of composition","PCFieldSplitSetType",PCCompositeTypes,(PetscEnum)jac->type,(PetscEnum*)&ctype,&flg);CHKERRQ(ierr); 6843b224e63SBarry Smith if (flg) { 6853b224e63SBarry Smith ierr = PCFieldSplitSetType(pc,ctype);CHKERRQ(ierr); 6863b224e63SBarry Smith } 687d32f9abdSBarry Smith 688c30613efSMatthew Knepley /* Only setup fields once */ 689c30613efSMatthew Knepley if ((jac->bs > 0) && (jac->nsplits == 0)) { 690d32f9abdSBarry Smith /* only allow user to set fields from command line if bs is already known. 691d32f9abdSBarry Smith otherwise user can set them in PCFieldSplitSetDefaults() */ 69251f519a2SBarry Smith ierr = PetscMalloc(jac->bs*sizeof(PetscInt),&fields);CHKERRQ(ierr); 6931b9fc7fcSBarry Smith while (PETSC_TRUE) { 69413f74950SBarry Smith sprintf(optionname,"-pc_fieldsplit_%d_fields",(int)i++); 69551f519a2SBarry Smith nfields = jac->bs; 6961b9fc7fcSBarry Smith ierr = PetscOptionsIntArray(optionname,"Fields in this split","PCFieldSplitSetFields",fields,&nfields,&flg);CHKERRQ(ierr); 6971b9fc7fcSBarry Smith if (!flg) break; 6981b9fc7fcSBarry Smith if (!nfields) SETERRQ(PETSC_ERR_USER,"Cannot list zero fields"); 6991b9fc7fcSBarry Smith ierr = PCFieldSplitSetFields(pc,nfields,fields);CHKERRQ(ierr); 7001b9fc7fcSBarry Smith } 70151f519a2SBarry Smith ierr = PetscFree(fields);CHKERRQ(ierr); 702d32f9abdSBarry Smith } 703084e4875SJed 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); 7041b9fc7fcSBarry Smith ierr = PetscOptionsTail();CHKERRQ(ierr); 7050971522cSBarry Smith PetscFunctionReturn(0); 7060971522cSBarry Smith } 7070971522cSBarry Smith 7080971522cSBarry Smith /*------------------------------------------------------------------------------------*/ 7090971522cSBarry Smith 7100971522cSBarry Smith EXTERN_C_BEGIN 7110971522cSBarry Smith #undef __FUNCT__ 7120971522cSBarry Smith #define __FUNCT__ "PCFieldSplitSetFields_FieldSplit" 713dba47a55SKris Buschelman PetscErrorCode PETSCKSP_DLLEXPORT PCFieldSplitSetFields_FieldSplit(PC pc,PetscInt n,PetscInt *fields) 7140971522cSBarry Smith { 71597bbdb24SBarry Smith PC_FieldSplit *jac = (PC_FieldSplit*)pc->data; 7160971522cSBarry Smith PetscErrorCode ierr; 7175a9f2f41SSatish Balay PC_FieldSplitLink ilink,next = jac->head; 71869a612a9SBarry Smith char prefix[128]; 71951f519a2SBarry Smith PetscInt i; 7200971522cSBarry Smith 7210971522cSBarry Smith PetscFunctionBegin; 7220971522cSBarry Smith if (n <= 0) SETERRQ(PETSC_ERR_ARG_OUTOFRANGE,"Negative number of fields requested"); 72351f519a2SBarry Smith for (i=0; i<n; i++) { 72451f519a2SBarry Smith if (fields[i] >= jac->bs) SETERRQ2(PETSC_ERR_ARG_OUTOFRANGE,"Field %D requested but only %D exist",fields[i],jac->bs); 72551f519a2SBarry Smith if (fields[i] < 0) SETERRQ1(PETSC_ERR_ARG_OUTOFRANGE,"Negative field %D requested",fields[i]); 72651f519a2SBarry Smith } 727704ba839SBarry Smith ierr = PetscNew(struct _PC_FieldSplitLink,&ilink);CHKERRQ(ierr); 728704ba839SBarry Smith ierr = PetscMalloc(n*sizeof(PetscInt),&ilink->fields);CHKERRQ(ierr); 7295a9f2f41SSatish Balay ierr = PetscMemcpy(ilink->fields,fields,n*sizeof(PetscInt));CHKERRQ(ierr); 7305a9f2f41SSatish Balay ilink->nfields = n; 7315a9f2f41SSatish Balay ilink->next = PETSC_NULL; 7327adad957SLisandro Dalcin ierr = KSPCreate(((PetscObject)pc)->comm,&ilink->ksp);CHKERRQ(ierr); 7331cee3971SBarry Smith ierr = PetscObjectIncrementTabLevel((PetscObject)ilink->ksp,(PetscObject)pc,1);CHKERRQ(ierr); 7345a9f2f41SSatish Balay ierr = KSPSetType(ilink->ksp,KSPPREONLY);CHKERRQ(ierr); 73569a612a9SBarry Smith 7367adad957SLisandro Dalcin if (((PetscObject)pc)->prefix) { 7377adad957SLisandro Dalcin sprintf(prefix,"%sfieldsplit_%d_",((PetscObject)pc)->prefix,(int)jac->nsplits); 73869a612a9SBarry Smith } else { 73913f74950SBarry Smith sprintf(prefix,"fieldsplit_%d_",(int)jac->nsplits); 74069a612a9SBarry Smith } 7415a9f2f41SSatish Balay ierr = KSPSetOptionsPrefix(ilink->ksp,prefix);CHKERRQ(ierr); 7420971522cSBarry Smith 7430971522cSBarry Smith if (!next) { 7445a9f2f41SSatish Balay jac->head = ilink; 74551f519a2SBarry Smith ilink->previous = PETSC_NULL; 7460971522cSBarry Smith } else { 7470971522cSBarry Smith while (next->next) { 7480971522cSBarry Smith next = next->next; 7490971522cSBarry Smith } 7505a9f2f41SSatish Balay next->next = ilink; 75151f519a2SBarry Smith ilink->previous = next; 7520971522cSBarry Smith } 7530971522cSBarry Smith jac->nsplits++; 7540971522cSBarry Smith PetscFunctionReturn(0); 7550971522cSBarry Smith } 7560971522cSBarry Smith EXTERN_C_END 7570971522cSBarry Smith 758e69d4d44SBarry Smith EXTERN_C_BEGIN 759e69d4d44SBarry Smith #undef __FUNCT__ 760e69d4d44SBarry Smith #define __FUNCT__ "PCFieldSplitGetSubKSP_FieldSplit_Schur" 761e69d4d44SBarry Smith PetscErrorCode PETSCKSP_DLLEXPORT PCFieldSplitGetSubKSP_FieldSplit_Schur(PC pc,PetscInt *n,KSP **subksp) 762e69d4d44SBarry Smith { 763e69d4d44SBarry Smith PC_FieldSplit *jac = (PC_FieldSplit*)pc->data; 764e69d4d44SBarry Smith PetscErrorCode ierr; 765e69d4d44SBarry Smith 766e69d4d44SBarry Smith PetscFunctionBegin; 767519d70e2SJed Brown ierr = PetscMalloc(jac->nsplits*sizeof(KSP),subksp);CHKERRQ(ierr); 768e69d4d44SBarry Smith ierr = MatSchurComplementGetKSP(jac->schur,*subksp);CHKERRQ(ierr); 769e69d4d44SBarry Smith (*subksp)[1] = jac->kspschur; 770084e4875SJed Brown *n = jac->nsplits; 771e69d4d44SBarry Smith PetscFunctionReturn(0); 772e69d4d44SBarry Smith } 773e69d4d44SBarry Smith EXTERN_C_END 7740971522cSBarry Smith 7750971522cSBarry Smith EXTERN_C_BEGIN 7760971522cSBarry Smith #undef __FUNCT__ 77769a612a9SBarry Smith #define __FUNCT__ "PCFieldSplitGetSubKSP_FieldSplit" 778dba47a55SKris Buschelman PetscErrorCode PETSCKSP_DLLEXPORT PCFieldSplitGetSubKSP_FieldSplit(PC pc,PetscInt *n,KSP **subksp) 7790971522cSBarry Smith { 7800971522cSBarry Smith PC_FieldSplit *jac = (PC_FieldSplit*)pc->data; 7810971522cSBarry Smith PetscErrorCode ierr; 7820971522cSBarry Smith PetscInt cnt = 0; 7835a9f2f41SSatish Balay PC_FieldSplitLink ilink = jac->head; 7840971522cSBarry Smith 7850971522cSBarry Smith PetscFunctionBegin; 78669a612a9SBarry Smith ierr = PetscMalloc(jac->nsplits*sizeof(KSP*),subksp);CHKERRQ(ierr); 7875a9f2f41SSatish Balay while (ilink) { 7885a9f2f41SSatish Balay (*subksp)[cnt++] = ilink->ksp; 7895a9f2f41SSatish Balay ilink = ilink->next; 7900971522cSBarry Smith } 7910971522cSBarry Smith if (cnt != jac->nsplits) SETERRQ2(PETSC_ERR_PLIB,"Corrupt PCFIELDSPLIT object: number splits in linked list %D in object %D",cnt,jac->nsplits); 7920971522cSBarry Smith *n = jac->nsplits; 7930971522cSBarry Smith PetscFunctionReturn(0); 7940971522cSBarry Smith } 7950971522cSBarry Smith EXTERN_C_END 7960971522cSBarry Smith 797704ba839SBarry Smith EXTERN_C_BEGIN 798704ba839SBarry Smith #undef __FUNCT__ 799704ba839SBarry Smith #define __FUNCT__ "PCFieldSplitSetIS_FieldSplit" 800704ba839SBarry Smith PetscErrorCode PETSCKSP_DLLEXPORT PCFieldSplitSetIS_FieldSplit(PC pc,IS is) 801704ba839SBarry Smith { 802704ba839SBarry Smith PC_FieldSplit *jac = (PC_FieldSplit*)pc->data; 803704ba839SBarry Smith PetscErrorCode ierr; 804704ba839SBarry Smith PC_FieldSplitLink ilink, next = jac->head; 805704ba839SBarry Smith char prefix[128]; 806704ba839SBarry Smith 807704ba839SBarry Smith PetscFunctionBegin; 80816913363SBarry Smith ierr = PetscNew(struct _PC_FieldSplitLink,&ilink);CHKERRQ(ierr); 8091ab39975SBarry Smith ilink->is = is; 8101ab39975SBarry Smith ierr = PetscObjectReference((PetscObject)is);CHKERRQ(ierr); 811704ba839SBarry Smith ilink->next = PETSC_NULL; 812704ba839SBarry Smith ierr = KSPCreate(((PetscObject)pc)->comm,&ilink->ksp);CHKERRQ(ierr); 8131cee3971SBarry Smith ierr = PetscObjectIncrementTabLevel((PetscObject)ilink->ksp,(PetscObject)pc,1);CHKERRQ(ierr); 814704ba839SBarry Smith ierr = KSPSetType(ilink->ksp,KSPPREONLY);CHKERRQ(ierr); 815704ba839SBarry Smith 816704ba839SBarry Smith if (((PetscObject)pc)->prefix) { 817704ba839SBarry Smith sprintf(prefix,"%sfieldsplit_%d_",((PetscObject)pc)->prefix,(int)jac->nsplits); 818704ba839SBarry Smith } else { 819704ba839SBarry Smith sprintf(prefix,"fieldsplit_%d_",(int)jac->nsplits); 820704ba839SBarry Smith } 821704ba839SBarry Smith ierr = KSPSetOptionsPrefix(ilink->ksp,prefix);CHKERRQ(ierr); 822704ba839SBarry Smith 823704ba839SBarry Smith if (!next) { 824704ba839SBarry Smith jac->head = ilink; 825704ba839SBarry Smith ilink->previous = PETSC_NULL; 826704ba839SBarry Smith } else { 827704ba839SBarry Smith while (next->next) { 828704ba839SBarry Smith next = next->next; 829704ba839SBarry Smith } 830704ba839SBarry Smith next->next = ilink; 831704ba839SBarry Smith ilink->previous = next; 832704ba839SBarry Smith } 833704ba839SBarry Smith jac->nsplits++; 834704ba839SBarry Smith 835704ba839SBarry Smith PetscFunctionReturn(0); 836704ba839SBarry Smith } 837704ba839SBarry Smith EXTERN_C_END 838704ba839SBarry Smith 8390971522cSBarry Smith #undef __FUNCT__ 8400971522cSBarry Smith #define __FUNCT__ "PCFieldSplitSetFields" 8410971522cSBarry Smith /*@ 8420971522cSBarry Smith PCFieldSplitSetFields - Sets the fields for one particular split in the field split preconditioner 8430971522cSBarry Smith 8440971522cSBarry Smith Collective on PC 8450971522cSBarry Smith 8460971522cSBarry Smith Input Parameters: 8470971522cSBarry Smith + pc - the preconditioner context 8480971522cSBarry Smith . n - the number of fields in this split 8490971522cSBarry Smith . fields - the fields in this split 8500971522cSBarry Smith 8510971522cSBarry Smith Level: intermediate 8520971522cSBarry Smith 853d32f9abdSBarry Smith Notes: Use PCFieldSplitSetIS() to set a completely general set of indices as a field. 854d32f9abdSBarry Smith 855d32f9abdSBarry Smith The PCFieldSplitSetFields() is for defining fields as a strided blocks. For example, if the block 856d32f9abdSBarry 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 857d32f9abdSBarry Smith 0xx3xx6xx9xx12 ... x1xx4xx7xx ... xx2xx5xx8xx.. 01x34x67x... 0x1x3x5x7.. x12x45x78x.... 858d32f9abdSBarry Smith where the numbered entries indicate what is in the field. 859d32f9abdSBarry Smith 860d32f9abdSBarry Smith .seealso: PCFieldSplitGetSubKSP(), PCFIELDSPLIT, PCFieldSplitSetBlockSize(), PCFieldSplitSetIS() 8610971522cSBarry Smith 8620971522cSBarry Smith @*/ 863dba47a55SKris Buschelman PetscErrorCode PETSCKSP_DLLEXPORT PCFieldSplitSetFields(PC pc,PetscInt n, PetscInt *fields) 8640971522cSBarry Smith { 8650971522cSBarry Smith PetscErrorCode ierr,(*f)(PC,PetscInt,PetscInt *); 8660971522cSBarry Smith 8670971522cSBarry Smith PetscFunctionBegin; 868*0700a824SBarry Smith PetscValidHeaderSpecific(pc,PC_CLASSID,1); 8690971522cSBarry Smith ierr = PetscObjectQueryFunction((PetscObject)pc,"PCFieldSplitSetFields_C",(void (**)(void))&f);CHKERRQ(ierr); 8700971522cSBarry Smith if (f) { 8710971522cSBarry Smith ierr = (*f)(pc,n,fields);CHKERRQ(ierr); 8720971522cSBarry Smith } 8730971522cSBarry Smith PetscFunctionReturn(0); 8740971522cSBarry Smith } 8750971522cSBarry Smith 8760971522cSBarry Smith #undef __FUNCT__ 877704ba839SBarry Smith #define __FUNCT__ "PCFieldSplitSetIS" 878704ba839SBarry Smith /*@ 879704ba839SBarry Smith PCFieldSplitSetIS - Sets the exact elements for field 880704ba839SBarry Smith 881704ba839SBarry Smith Collective on PC 882704ba839SBarry Smith 883704ba839SBarry Smith Input Parameters: 884704ba839SBarry Smith + pc - the preconditioner context 885704ba839SBarry Smith . is - the index set that defines the vector elements in this field 886704ba839SBarry Smith 887d32f9abdSBarry Smith 888d32f9abdSBarry Smith Notes: Use PCFieldSplitSetFields(), for fields defined by strided types. 889d32f9abdSBarry Smith 890704ba839SBarry Smith Level: intermediate 891704ba839SBarry Smith 892704ba839SBarry Smith .seealso: PCFieldSplitGetSubKSP(), PCFIELDSPLIT, PCFieldSplitSetBlockSize() 893704ba839SBarry Smith 894704ba839SBarry Smith @*/ 895704ba839SBarry Smith PetscErrorCode PETSCKSP_DLLEXPORT PCFieldSplitSetIS(PC pc,IS is) 896704ba839SBarry Smith { 897704ba839SBarry Smith PetscErrorCode ierr,(*f)(PC,IS); 898704ba839SBarry Smith 899704ba839SBarry Smith PetscFunctionBegin; 900*0700a824SBarry Smith PetscValidHeaderSpecific(pc,PC_CLASSID,1); 901*0700a824SBarry Smith PetscValidHeaderSpecific(is,IS_CLASSID,1); 902704ba839SBarry Smith ierr = PetscObjectQueryFunction((PetscObject)pc,"PCFieldSplitSetIS_C",(void (**)(void))&f);CHKERRQ(ierr); 903704ba839SBarry Smith if (f) { 904704ba839SBarry Smith ierr = (*f)(pc,is);CHKERRQ(ierr); 905704ba839SBarry Smith } 906704ba839SBarry Smith PetscFunctionReturn(0); 907704ba839SBarry Smith } 908704ba839SBarry Smith 909704ba839SBarry Smith #undef __FUNCT__ 91051f519a2SBarry Smith #define __FUNCT__ "PCFieldSplitSetBlockSize" 91151f519a2SBarry Smith /*@ 91251f519a2SBarry Smith PCFieldSplitSetBlockSize - Sets the block size for defining where fields start in the 91351f519a2SBarry Smith fieldsplit preconditioner. If not set the matrix block size is used. 91451f519a2SBarry Smith 91551f519a2SBarry Smith Collective on PC 91651f519a2SBarry Smith 91751f519a2SBarry Smith Input Parameters: 91851f519a2SBarry Smith + pc - the preconditioner context 91951f519a2SBarry Smith - bs - the block size 92051f519a2SBarry Smith 92151f519a2SBarry Smith Level: intermediate 92251f519a2SBarry Smith 92351f519a2SBarry Smith .seealso: PCFieldSplitGetSubKSP(), PCFIELDSPLIT, PCFieldSplitSetFields() 92451f519a2SBarry Smith 92551f519a2SBarry Smith @*/ 92651f519a2SBarry Smith PetscErrorCode PETSCKSP_DLLEXPORT PCFieldSplitSetBlockSize(PC pc,PetscInt bs) 92751f519a2SBarry Smith { 92851f519a2SBarry Smith PetscErrorCode ierr,(*f)(PC,PetscInt); 92951f519a2SBarry Smith 93051f519a2SBarry Smith PetscFunctionBegin; 931*0700a824SBarry Smith PetscValidHeaderSpecific(pc,PC_CLASSID,1); 93251f519a2SBarry Smith ierr = PetscObjectQueryFunction((PetscObject)pc,"PCFieldSplitSetBlockSize_C",(void (**)(void))&f);CHKERRQ(ierr); 93351f519a2SBarry Smith if (f) { 93451f519a2SBarry Smith ierr = (*f)(pc,bs);CHKERRQ(ierr); 93551f519a2SBarry Smith } 93651f519a2SBarry Smith PetscFunctionReturn(0); 93751f519a2SBarry Smith } 93851f519a2SBarry Smith 93951f519a2SBarry Smith #undef __FUNCT__ 94069a612a9SBarry Smith #define __FUNCT__ "PCFieldSplitGetSubKSP" 9410971522cSBarry Smith /*@C 94269a612a9SBarry Smith PCFieldSplitGetSubKSP - Gets the KSP contexts for all splits 9430971522cSBarry Smith 94469a612a9SBarry Smith Collective on KSP 9450971522cSBarry Smith 9460971522cSBarry Smith Input Parameter: 9470971522cSBarry Smith . pc - the preconditioner context 9480971522cSBarry Smith 9490971522cSBarry Smith Output Parameters: 9500971522cSBarry Smith + n - the number of split 95169a612a9SBarry Smith - pc - the array of KSP contexts 9520971522cSBarry Smith 9530971522cSBarry Smith Note: 954d32f9abdSBarry Smith After PCFieldSplitGetSubKSP() the array of KSPs IS to be freed by the user 955d32f9abdSBarry Smith (not the KSP just the array that contains them). 9560971522cSBarry Smith 95769a612a9SBarry Smith You must call KSPSetUp() before calling PCFieldSplitGetSubKSP(). 9580971522cSBarry Smith 9590971522cSBarry Smith Level: advanced 9600971522cSBarry Smith 9610971522cSBarry Smith .seealso: PCFIELDSPLIT 9620971522cSBarry Smith @*/ 963dba47a55SKris Buschelman PetscErrorCode PETSCKSP_DLLEXPORT PCFieldSplitGetSubKSP(PC pc,PetscInt *n,KSP *subksp[]) 9640971522cSBarry Smith { 96569a612a9SBarry Smith PetscErrorCode ierr,(*f)(PC,PetscInt*,KSP **); 9660971522cSBarry Smith 9670971522cSBarry Smith PetscFunctionBegin; 968*0700a824SBarry Smith PetscValidHeaderSpecific(pc,PC_CLASSID,1); 9690971522cSBarry Smith PetscValidIntPointer(n,2); 97069a612a9SBarry Smith ierr = PetscObjectQueryFunction((PetscObject)pc,"PCFieldSplitGetSubKSP_C",(void (**)(void))&f);CHKERRQ(ierr); 9710971522cSBarry Smith if (f) { 97269a612a9SBarry Smith ierr = (*f)(pc,n,subksp);CHKERRQ(ierr); 9730971522cSBarry Smith } else { 97469a612a9SBarry Smith SETERRQ(PETSC_ERR_ARG_WRONG,"Cannot get subksp for this type of PC"); 9750971522cSBarry Smith } 9760971522cSBarry Smith PetscFunctionReturn(0); 9770971522cSBarry Smith } 9780971522cSBarry Smith 979e69d4d44SBarry Smith #undef __FUNCT__ 980e69d4d44SBarry Smith #define __FUNCT__ "PCFieldSplitSchurPrecondition" 981e69d4d44SBarry Smith /*@ 982e69d4d44SBarry Smith PCFieldSplitSchurPrecondition - Indicates if the Schur complement is preconditioned by a preconditioner constructed by the 983e69d4d44SBarry Smith D matrix. Otherwise no preconditioner is used. 984e69d4d44SBarry Smith 985e69d4d44SBarry Smith Collective on PC 986e69d4d44SBarry Smith 987e69d4d44SBarry Smith Input Parameters: 988e69d4d44SBarry Smith + pc - the preconditioner context 989084e4875SJed Brown . ptype - which matrix to use for preconditioning the Schur complement 990084e4875SJed Brown - userpre - matrix to use for preconditioning, or PETSC_NULL 991084e4875SJed Brown 992084e4875SJed Brown Notes: 993084e4875SJed Brown The default is to use the block on the diagonal of the preconditioning matrix. This is D, in the (1,1) position. 994084e4875SJed Brown There are currently no preconditioners that work directly with the Schur complement so setting 995084e4875SJed Brown PC_FIELDSPLIT_SCHUR_PRE_SELF is observationally equivalent to -fieldsplit_1_pc_type none. 996e69d4d44SBarry Smith 997e69d4d44SBarry Smith Options Database: 998084e4875SJed Brown . -pc_fieldsplit_schur_precondition <self,user,diag> default is diag 999e69d4d44SBarry Smith 1000e69d4d44SBarry Smith Level: intermediate 1001e69d4d44SBarry Smith 1002084e4875SJed Brown .seealso: PCFieldSplitGetSubKSP(), PCFIELDSPLIT, PCFieldSplitSetFields(), PCFieldSplitSchurPreType 1003e69d4d44SBarry Smith 1004e69d4d44SBarry Smith @*/ 1005084e4875SJed Brown PetscErrorCode PETSCKSP_DLLEXPORT PCFieldSplitSchurPrecondition(PC pc,PCFieldSplitSchurPreType ptype,Mat pre) 1006e69d4d44SBarry Smith { 1007084e4875SJed Brown PetscErrorCode ierr,(*f)(PC,PCFieldSplitSchurPreType,Mat); 1008e69d4d44SBarry Smith 1009e69d4d44SBarry Smith PetscFunctionBegin; 1010*0700a824SBarry Smith PetscValidHeaderSpecific(pc,PC_CLASSID,1); 1011e69d4d44SBarry Smith ierr = PetscObjectQueryFunction((PetscObject)pc,"PCFieldSplitSchurPrecondition_C",(void (**)(void))&f);CHKERRQ(ierr); 1012e69d4d44SBarry Smith if (f) { 1013084e4875SJed Brown ierr = (*f)(pc,ptype,pre);CHKERRQ(ierr); 1014e69d4d44SBarry Smith } 1015e69d4d44SBarry Smith PetscFunctionReturn(0); 1016e69d4d44SBarry Smith } 1017e69d4d44SBarry Smith 1018e69d4d44SBarry Smith EXTERN_C_BEGIN 1019e69d4d44SBarry Smith #undef __FUNCT__ 1020e69d4d44SBarry Smith #define __FUNCT__ "PCFieldSplitSchurPrecondition_FieldSplit" 1021084e4875SJed Brown PetscErrorCode PETSCKSP_DLLEXPORT PCFieldSplitSchurPrecondition_FieldSplit(PC pc,PCFieldSplitSchurPreType ptype,Mat pre) 1022e69d4d44SBarry Smith { 1023e69d4d44SBarry Smith PC_FieldSplit *jac = (PC_FieldSplit*)pc->data; 1024084e4875SJed Brown PetscErrorCode ierr; 1025e69d4d44SBarry Smith 1026e69d4d44SBarry Smith PetscFunctionBegin; 1027084e4875SJed Brown jac->schurpre = ptype; 1028084e4875SJed Brown if (pre) { 1029084e4875SJed Brown if (jac->schur_user) {ierr = MatDestroy(jac->schur_user);CHKERRQ(ierr);} 1030084e4875SJed Brown jac->schur_user = pre; 1031084e4875SJed Brown ierr = PetscObjectReference((PetscObject)jac->schur_user);CHKERRQ(ierr); 1032084e4875SJed Brown } 1033e69d4d44SBarry Smith PetscFunctionReturn(0); 1034e69d4d44SBarry Smith } 1035e69d4d44SBarry Smith EXTERN_C_END 1036e69d4d44SBarry Smith 103730ad9308SMatthew Knepley #undef __FUNCT__ 103830ad9308SMatthew Knepley #define __FUNCT__ "PCFieldSplitGetSchurBlocks" 103930ad9308SMatthew Knepley /*@C 104030ad9308SMatthew Knepley PCFieldSplitGetSchurBlocks - Gets the all matrix blocks for the Schur complement 104130ad9308SMatthew Knepley 104230ad9308SMatthew Knepley Collective on KSP 104330ad9308SMatthew Knepley 104430ad9308SMatthew Knepley Input Parameter: 104530ad9308SMatthew Knepley . pc - the preconditioner context 104630ad9308SMatthew Knepley 104730ad9308SMatthew Knepley Output Parameters: 104830ad9308SMatthew Knepley + A - the (0,0) block 104930ad9308SMatthew Knepley . B - the (0,1) block 105030ad9308SMatthew Knepley . C - the (1,0) block 105130ad9308SMatthew Knepley - D - the (1,1) block 105230ad9308SMatthew Knepley 105330ad9308SMatthew Knepley Level: advanced 105430ad9308SMatthew Knepley 105530ad9308SMatthew Knepley .seealso: PCFIELDSPLIT 105630ad9308SMatthew Knepley @*/ 105730ad9308SMatthew Knepley PetscErrorCode PETSCKSP_DLLEXPORT PCFieldSplitGetSchurBlocks(PC pc,Mat *A,Mat *B,Mat *C, Mat *D) 105830ad9308SMatthew Knepley { 105930ad9308SMatthew Knepley PC_FieldSplit *jac = (PC_FieldSplit *) pc->data; 106030ad9308SMatthew Knepley 106130ad9308SMatthew Knepley PetscFunctionBegin; 1062*0700a824SBarry Smith PetscValidHeaderSpecific(pc,PC_CLASSID,1); 1063cf8ad460SMatthew Knepley if (jac->type != PC_COMPOSITE_SCHUR) {SETERRQ(PETSC_ERR_ARG_WRONG, "FieldSplit is not using a Schur complement approach.");} 106430ad9308SMatthew Knepley if (A) *A = jac->pmat[0]; 106530ad9308SMatthew Knepley if (B) *B = jac->B; 106630ad9308SMatthew Knepley if (C) *C = jac->C; 106730ad9308SMatthew Knepley if (D) *D = jac->pmat[1]; 106830ad9308SMatthew Knepley PetscFunctionReturn(0); 106930ad9308SMatthew Knepley } 107030ad9308SMatthew Knepley 107179416396SBarry Smith EXTERN_C_BEGIN 107279416396SBarry Smith #undef __FUNCT__ 107379416396SBarry Smith #define __FUNCT__ "PCFieldSplitSetType_FieldSplit" 1074dba47a55SKris Buschelman PetscErrorCode PETSCKSP_DLLEXPORT PCFieldSplitSetType_FieldSplit(PC pc,PCCompositeType type) 107579416396SBarry Smith { 107679416396SBarry Smith PC_FieldSplit *jac = (PC_FieldSplit*)pc->data; 1077e69d4d44SBarry Smith PetscErrorCode ierr; 107879416396SBarry Smith 107979416396SBarry Smith PetscFunctionBegin; 108079416396SBarry Smith jac->type = type; 10813b224e63SBarry Smith if (type == PC_COMPOSITE_SCHUR) { 10823b224e63SBarry Smith pc->ops->apply = PCApply_FieldSplit_Schur; 10833b224e63SBarry Smith pc->ops->view = PCView_FieldSplit_Schur; 1084e69d4d44SBarry Smith ierr = PetscObjectComposeFunctionDynamic((PetscObject)pc,"PCFieldSplitGetSubKSP_C","PCFieldSplitGetSubKSP_FieldSplit_Schur",PCFieldSplitGetSubKSP_FieldSplit_Schur);CHKERRQ(ierr); 1085e69d4d44SBarry Smith ierr = PetscObjectComposeFunctionDynamic((PetscObject)pc,"PCFieldSplitSchurPrecondition_C","PCFieldSplitSchurPrecondition_FieldSplit",PCFieldSplitSchurPrecondition_FieldSplit);CHKERRQ(ierr); 1086e69d4d44SBarry Smith 10873b224e63SBarry Smith } else { 10883b224e63SBarry Smith pc->ops->apply = PCApply_FieldSplit; 10893b224e63SBarry Smith pc->ops->view = PCView_FieldSplit; 1090e69d4d44SBarry Smith ierr = PetscObjectComposeFunctionDynamic((PetscObject)pc,"PCFieldSplitGetSubKSP_C","PCFieldSplitGetSubKSP_FieldSplit",PCFieldSplitGetSubKSP_FieldSplit);CHKERRQ(ierr); 10919e7d6b0aSBarry Smith ierr = PetscObjectComposeFunctionDynamic((PetscObject)pc,"PCFieldSplitSchurPrecondition_C","",0);CHKERRQ(ierr); 10923b224e63SBarry Smith } 109379416396SBarry Smith PetscFunctionReturn(0); 109479416396SBarry Smith } 109579416396SBarry Smith EXTERN_C_END 109679416396SBarry Smith 109751f519a2SBarry Smith EXTERN_C_BEGIN 109851f519a2SBarry Smith #undef __FUNCT__ 109951f519a2SBarry Smith #define __FUNCT__ "PCFieldSplitSetBlockSize_FieldSplit" 110051f519a2SBarry Smith PetscErrorCode PETSCKSP_DLLEXPORT PCFieldSplitSetBlockSize_FieldSplit(PC pc,PetscInt bs) 110151f519a2SBarry Smith { 110251f519a2SBarry Smith PC_FieldSplit *jac = (PC_FieldSplit*)pc->data; 110351f519a2SBarry Smith 110451f519a2SBarry Smith PetscFunctionBegin; 110551f519a2SBarry Smith if (bs < 1) SETERRQ1(PETSC_ERR_ARG_OUTOFRANGE,"Blocksize must be positive, you gave %D",bs); 110651f519a2SBarry 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); 110751f519a2SBarry Smith jac->bs = bs; 110851f519a2SBarry Smith PetscFunctionReturn(0); 110951f519a2SBarry Smith } 111051f519a2SBarry Smith EXTERN_C_END 111151f519a2SBarry Smith 111279416396SBarry Smith #undef __FUNCT__ 111379416396SBarry Smith #define __FUNCT__ "PCFieldSplitSetType" 1114bc08b0f1SBarry Smith /*@ 111579416396SBarry Smith PCFieldSplitSetType - Sets the type of fieldsplit preconditioner. 111679416396SBarry Smith 111779416396SBarry Smith Collective on PC 111879416396SBarry Smith 111979416396SBarry Smith Input Parameter: 112079416396SBarry Smith . pc - the preconditioner context 112181540f2fSBarry Smith . type - PC_COMPOSITE_ADDITIVE, PC_COMPOSITE_MULTIPLICATIVE (default), PC_COMPOSITE_SYMMETRIC_MULTIPLICATIVE, PC_COMPOSITE_SPECIAL, PC_COMPOSITE_SCHUR 112279416396SBarry Smith 112379416396SBarry Smith Options Database Key: 1124a4efd8eaSMatthew Knepley . -pc_fieldsplit_type <type: one of multiplicative, additive, symmetric_multiplicative, special, schur> - Sets fieldsplit preconditioner type 112579416396SBarry Smith 112679416396SBarry Smith Level: Developer 112779416396SBarry Smith 112879416396SBarry Smith .keywords: PC, set, type, composite preconditioner, additive, multiplicative 112979416396SBarry Smith 113079416396SBarry Smith .seealso: PCCompositeSetType() 113179416396SBarry Smith 113279416396SBarry Smith @*/ 1133dba47a55SKris Buschelman PetscErrorCode PETSCKSP_DLLEXPORT PCFieldSplitSetType(PC pc,PCCompositeType type) 113479416396SBarry Smith { 113579416396SBarry Smith PetscErrorCode ierr,(*f)(PC,PCCompositeType); 113679416396SBarry Smith 113779416396SBarry Smith PetscFunctionBegin; 1138*0700a824SBarry Smith PetscValidHeaderSpecific(pc,PC_CLASSID,1); 113979416396SBarry Smith ierr = PetscObjectQueryFunction((PetscObject)pc,"PCFieldSplitSetType_C",(void (**)(void))&f);CHKERRQ(ierr); 114079416396SBarry Smith if (f) { 114179416396SBarry Smith ierr = (*f)(pc,type);CHKERRQ(ierr); 114279416396SBarry Smith } 114379416396SBarry Smith PetscFunctionReturn(0); 114479416396SBarry Smith } 114579416396SBarry Smith 11460971522cSBarry Smith /* -------------------------------------------------------------------------------------*/ 11470971522cSBarry Smith /*MC 1148a8c7a070SBarry Smith PCFIELDSPLIT - Preconditioner created by combining separate preconditioners for individual 11490971522cSBarry Smith fields or groups of fields 11500971522cSBarry Smith 11510971522cSBarry Smith 1152edf189efSBarry Smith To set options on the solvers for each block append -fieldsplit_ to all the PC 1153edf189efSBarry Smith options database keys. For example, -fieldsplit_pc_type ilu -fieldsplit_pc_factor_levels 1 11540971522cSBarry Smith 1155a8c7a070SBarry Smith To set the options on the solvers separate for each block call PCFieldSplitGetSubKSP() 115669a612a9SBarry Smith and set the options directly on the resulting KSP object 11570971522cSBarry Smith 11580971522cSBarry Smith Level: intermediate 11590971522cSBarry Smith 116079416396SBarry Smith Options Database Keys: 116181540f2fSBarry Smith + -pc_fieldsplit_%d_fields <a,b,..> - indicates the fields to be used in the %d'th split 116281540f2fSBarry Smith . -pc_fieldsplit_default - automatically add any fields to additional splits that have not 116381540f2fSBarry Smith been supplied explicitly by -pc_fieldsplit_%d_fields 116481540f2fSBarry Smith . -pc_fieldsplit_block_size <bs> - size of block that defines fields (i.e. there are bs fields) 116581540f2fSBarry Smith . -pc_fieldsplit_type <additive,multiplicative,schur,symmetric_multiplicative> 1166e69d4d44SBarry Smith . -pc_fieldsplit_schur_precondition <true,false> default is true 116779416396SBarry Smith 1168edf189efSBarry Smith - Options prefix for inner solvers when using Schur complement preconditioner are -fieldsplit_0_ and -fieldsplit_1_ 11693b224e63SBarry Smith for all other solvers they are -fieldsplit_%d_ for the dth field, use -fieldsplit_ for all fields 11703b224e63SBarry Smith 11713b224e63SBarry Smith 1172d32f9abdSBarry Smith Notes: use PCFieldSplitSetFields() to set fields defined by "strided" entries and PCFieldSplitSetIS() 1173d32f9abdSBarry Smith to define a field by an arbitrary collection of entries. 1174d32f9abdSBarry Smith 1175d32f9abdSBarry Smith If no fields are set the default is used. The fields are defined by entries strided by bs, 1176d32f9abdSBarry Smith beginning at 0 then 1, etc to bs-1. The block size can be set with PCFieldSplitSetBlockSize(), 1177d32f9abdSBarry Smith if this is not called the block size defaults to the blocksize of the second matrix passed 1178d32f9abdSBarry Smith to KSPSetOperators()/PCSetOperators(). 1179d32f9abdSBarry Smith 1180d32f9abdSBarry Smith Currently for the multiplicative version, the updated residual needed for the next field 1181d32f9abdSBarry Smith solve is computed via a matrix vector product over the entire array. An optimization would be 1182d32f9abdSBarry Smith to update the residual only for the part of the right hand side associated with the next field 1183d32f9abdSBarry Smith solve. (This would involve more MatGetSubMatrix() calls or some other mechanism to compute the 1184d32f9abdSBarry Smith part of the matrix needed to just update part of the residual). 1185d32f9abdSBarry Smith 1186e69d4d44SBarry Smith For the Schur complement preconditioner if J = ( A B ) 1187e69d4d44SBarry Smith ( C D ) 1188e69d4d44SBarry Smith the preconditioner is 1189e69d4d44SBarry Smith (I -B inv(A)) ( inv(A) 0 ) (I 0 ) 1190e69d4d44SBarry Smith (0 I ) ( 0 inv(S) ) (-C inv(A) I ) 1191edf189efSBarry Smith where the action of inv(A) is applied using the KSP solver with prefix -fieldsplit_0_. The action of 1192e69d4d44SBarry Smith inv(S) is computed using the KSP solver with prefix -schur_. For PCFieldSplitGetKSP() when field number is 1193edf189efSBarry Smith 0 it returns the KSP associated with -fieldsplit_0_ while field number 1 gives -fieldsplit_1_ KSP. By default 1194e69d4d44SBarry Smith D is used to construct a preconditioner for S, use PCFieldSplitSchurPrecondition() to turn on or off this 1195e69d4d44SBarry Smith option. 1196e69d4d44SBarry Smith 1197edf189efSBarry Smith If only one set of indices (one IS) is provided with PCFieldSplitSetIS() then the complement of that IS 1198edf189efSBarry Smith is used automatically for a second block. 1199edf189efSBarry Smith 1200a541d17aSBarry Smith Concepts: physics based preconditioners, block preconditioners 12010971522cSBarry Smith 1202a541d17aSBarry Smith .seealso: PCCreate(), PCSetType(), PCType (for list of available types), PC, Block_Preconditioners 1203e69d4d44SBarry Smith PCFieldSplitGetSubKSP(), PCFieldSplitSetFields(), PCFieldSplitSetType(), PCFieldSplitSetIS(), PCFieldSplitSchurPrecondition() 12040971522cSBarry Smith M*/ 12050971522cSBarry Smith 12060971522cSBarry Smith EXTERN_C_BEGIN 12070971522cSBarry Smith #undef __FUNCT__ 12080971522cSBarry Smith #define __FUNCT__ "PCCreate_FieldSplit" 1209dba47a55SKris Buschelman PetscErrorCode PETSCKSP_DLLEXPORT PCCreate_FieldSplit(PC pc) 12100971522cSBarry Smith { 12110971522cSBarry Smith PetscErrorCode ierr; 12120971522cSBarry Smith PC_FieldSplit *jac; 12130971522cSBarry Smith 12140971522cSBarry Smith PetscFunctionBegin; 121538f2d2fdSLisandro Dalcin ierr = PetscNewLog(pc,PC_FieldSplit,&jac);CHKERRQ(ierr); 12160971522cSBarry Smith jac->bs = -1; 12170971522cSBarry Smith jac->nsplits = 0; 12183e197d65SBarry Smith jac->type = PC_COMPOSITE_MULTIPLICATIVE; 1219e6cab6aaSJed Brown jac->schurpre = PC_FIELDSPLIT_SCHUR_PRE_USER; /* Try user preconditioner first, fall back on diagonal */ 122051f519a2SBarry Smith 12210971522cSBarry Smith pc->data = (void*)jac; 12220971522cSBarry Smith 12230971522cSBarry Smith pc->ops->apply = PCApply_FieldSplit; 1224421e10b8SBarry Smith pc->ops->applytranspose = PCApplyTranspose_FieldSplit; 12250971522cSBarry Smith pc->ops->setup = PCSetUp_FieldSplit; 12260971522cSBarry Smith pc->ops->destroy = PCDestroy_FieldSplit; 12270971522cSBarry Smith pc->ops->setfromoptions = PCSetFromOptions_FieldSplit; 12280971522cSBarry Smith pc->ops->view = PCView_FieldSplit; 12290971522cSBarry Smith pc->ops->applyrichardson = 0; 12300971522cSBarry Smith 123169a612a9SBarry Smith ierr = PetscObjectComposeFunctionDynamic((PetscObject)pc,"PCFieldSplitGetSubKSP_C","PCFieldSplitGetSubKSP_FieldSplit", 123269a612a9SBarry Smith PCFieldSplitGetSubKSP_FieldSplit);CHKERRQ(ierr); 12330971522cSBarry Smith ierr = PetscObjectComposeFunctionDynamic((PetscObject)pc,"PCFieldSplitSetFields_C","PCFieldSplitSetFields_FieldSplit", 12340971522cSBarry Smith PCFieldSplitSetFields_FieldSplit);CHKERRQ(ierr); 1235704ba839SBarry Smith ierr = PetscObjectComposeFunctionDynamic((PetscObject)pc,"PCFieldSplitSetIS_C","PCFieldSplitSetIS_FieldSplit", 1236704ba839SBarry Smith PCFieldSplitSetIS_FieldSplit);CHKERRQ(ierr); 123779416396SBarry Smith ierr = PetscObjectComposeFunctionDynamic((PetscObject)pc,"PCFieldSplitSetType_C","PCFieldSplitSetType_FieldSplit", 123879416396SBarry Smith PCFieldSplitSetType_FieldSplit);CHKERRQ(ierr); 123951f519a2SBarry Smith ierr = PetscObjectComposeFunctionDynamic((PetscObject)pc,"PCFieldSplitSetBlockSize_C","PCFieldSplitSetBlockSize_FieldSplit", 124051f519a2SBarry Smith PCFieldSplitSetBlockSize_FieldSplit);CHKERRQ(ierr); 12410971522cSBarry Smith PetscFunctionReturn(0); 12420971522cSBarry Smith } 12430971522cSBarry Smith EXTERN_C_END 12440971522cSBarry Smith 12450971522cSBarry Smith 1246a541d17aSBarry Smith /*MC 1247a541d17aSBarry Smith Block_Preconditioners - PETSc provides support for a variety of "block preconditioners", this provides an 1248a541d17aSBarry Smith overview of these methods. 1249a541d17aSBarry Smith 1250a541d17aSBarry Smith Consider the solution to ( A B ) (x_1) = (b_1) 1251a541d17aSBarry Smith ( C D ) (x_2) (b_2) 1252a541d17aSBarry Smith 1253a541d17aSBarry Smith Important special cases, the Stokes equation: C = B' and D = 0 (A B) (x_1) = (b_1) 1254a541d17aSBarry Smith B' 0) (x_2) (b_2) 1255a541d17aSBarry Smith 1256a541d17aSBarry Smith One of the goals of the PCFieldSplit preconditioner in PETSc is to provide a variety of preconditioners 1257a541d17aSBarry Smith for this block system. 1258a541d17aSBarry Smith 1259a541d17aSBarry Smith Consider an additional matrix (Ap Bp) 1260a541d17aSBarry Smith (Cp Dp) where some or all of the entries may be the same as 1261a541d17aSBarry Smith in the original matrix (for example Ap == A). 1262a541d17aSBarry Smith 1263a541d17aSBarry Smith In the following, A^ denotes the approximate application of the inverse of A, possibly using Ap in the 1264a541d17aSBarry Smith approximation. In PETSc this simply means one has called KSPSetOperators(ksp,A,Ap,...) or KSPSetOperators(ksp,Ap,Ap,...) 1265a541d17aSBarry Smith 1266a541d17aSBarry Smith Block Jacobi: x_1 = A^ b_1 1267a541d17aSBarry Smith x_2 = D^ b_2 1268a541d17aSBarry Smith 1269a541d17aSBarry Smith Lower block Gauss-Seidel: x_1 = A^ b_1 1270a541d17aSBarry Smith x_2 = D^ (b_2 - C x_1) variant x_2 = D^ (b_2 - Cp x_1) 1271a541d17aSBarry Smith 1272a541d17aSBarry 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) 1273a541d17aSBarry Smith Interestingly this form is not actually a symmetric matrix, the symmetric version is 1274a541d17aSBarry Smith x_1 = A^(b_1 - B x_2) variant x_1 = A^(b_1 - Bp x_2) 1275a541d17aSBarry Smith 12760bc0a719SBarry Smith Level: intermediate 12770bc0a719SBarry Smith 1278a541d17aSBarry Smith .seealso: PCCreate(), PCSetType(), PCType (for list of available types), PC, PCFIELDSPLIT 1279a541d17aSBarry Smith PCFieldSplitGetSubKSP(), PCFieldSplitSetFields(), PCFieldSplitSetType(), PCFieldSplitSetIS(), PCFieldSplitSchurPrecondition() 1280a541d17aSBarry Smith M*/ 1281