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