1dba47a55SKris Buschelman 2b45d2f2cSJed Brown #include <petsc-private/pcimpl.h> /*I "petscpc.h" I*/ 31e25c274SJed Brown #include <petscdm.h> 40971522cSBarry Smith 5443836d0SMatthew G Knepley /* 6443836d0SMatthew G Knepley There is a nice discussion of block preconditioners in 7443836d0SMatthew G Knepley 81997fe2eSSatish Balay [El08] A taxonomy and comparison of parallel block multi-level preconditioners for the incompressible Navier-Stokes equations 9443836d0SMatthew G Knepley Howard Elman, V.E. Howle, John Shadid, Robert Shuttleworth, Ray Tuminaro, Journal of Computational Physics 227 (2008) 1790--1808 101b8e4c5fSJed Brown http://chess.cs.umd.edu/~elman/papers/tax.pdf 11443836d0SMatthew G Knepley */ 12443836d0SMatthew G Knepley 13a7476a74SDmitry Karpeev const char *const PCFieldSplitSchurPreTypes[] = {"SELF","SELFP","A11","USER","PCFieldSplitSchurPreType","PC_FIELDSPLIT_SCHUR_PRE_",0}; 14c9c6ffaaSJed Brown const char *const PCFieldSplitSchurFactTypes[] = {"DIAG","LOWER","UPPER","FULL","PCFieldSplitSchurFactType","PC_FIELDSPLIT_SCHUR_FACT_",0}; 15c5d2311dSJed Brown 160971522cSBarry Smith typedef struct _PC_FieldSplitLink *PC_FieldSplitLink; 170971522cSBarry Smith struct _PC_FieldSplitLink { 1869a612a9SBarry Smith KSP ksp; 19443836d0SMatthew G Knepley Vec x,y,z; 20db4c96c1SJed Brown char *splitname; 210971522cSBarry Smith PetscInt nfields; 225d4c12cdSJungho Lee PetscInt *fields,*fields_col; 231b9fc7fcSBarry Smith VecScatter sctx; 245d4c12cdSJungho Lee IS is,is_col; 2551f519a2SBarry Smith PC_FieldSplitLink next,previous; 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 */ 45*45e7fc46SDmitry Karpeev PetscBool schurp_lump; /* Whether to lump A00 when forming Sp. */ 46084e4875SJed Brown Mat schur_user; /* User-provided preconditioning matrix for the Schur complement */ 47084e4875SJed Brown PCFieldSplitSchurPreType schurpre; /* Determines which preconditioning matrix is used for the Schur complement */ 48c9c6ffaaSJed Brown PCFieldSplitSchurFactType schurfactorization; 4930ad9308SMatthew Knepley KSP kspschur; /* The solver for S */ 50443836d0SMatthew G Knepley KSP kspupper; /* The solver for A in the upper diagonal part of the factorization (H_2 in [El08]) */ 5197bbdb24SBarry Smith PC_FieldSplitLink head; 5263ec74ffSBarry Smith PetscBool reset; /* indicates PCReset() has been last called on this object, hack */ 53c1570756SJed Brown PetscBool suboptionsset; /* Indicates that the KSPSetFromOptions() has been called on the sub-KSPs */ 544ab8060aSDmitry Karpeev PetscBool dm_splits; /* Whether to use DMCreateFieldDecomposition() whenever possible */ 550971522cSBarry Smith } PC_FieldSplit; 560971522cSBarry Smith 5716913363SBarry Smith /* 5816913363SBarry Smith Notes: there is no particular reason that pmat, x, and y are stored as arrays in PC_FieldSplit instead of 5916913363SBarry Smith inside PC_FieldSplitLink, just historical. If you want to be able to add new fields after already using the 6016913363SBarry Smith PC you could change this. 6116913363SBarry Smith */ 62084e4875SJed Brown 63e6cab6aaSJed Brown /* This helper is so that setting a user-provided preconditioning matrix is orthogonal to choosing to use it. This way the 64084e4875SJed Brown * application-provided FormJacobian can provide this matrix without interfering with the user's (command-line) choices. */ 65084e4875SJed Brown static Mat FieldSplitSchurPre(PC_FieldSplit *jac) 66084e4875SJed Brown { 67084e4875SJed Brown switch (jac->schurpre) { 68084e4875SJed Brown case PC_FIELDSPLIT_SCHUR_PRE_SELF: return jac->schur; 69a7476a74SDmitry Karpeev case PC_FIELDSPLIT_SCHUR_PRE_SELFP: return jac->schurp; 70e87fab1bSBarry Smith case PC_FIELDSPLIT_SCHUR_PRE_A11: return jac->pmat[1]; 71084e4875SJed Brown case PC_FIELDSPLIT_SCHUR_PRE_USER: /* Use a user-provided matrix if it is given, otherwise diagonal block */ 72084e4875SJed Brown default: 73084e4875SJed Brown return jac->schur_user ? jac->schur_user : jac->pmat[1]; 74084e4875SJed Brown } 75084e4875SJed Brown } 76084e4875SJed Brown 77084e4875SJed Brown 789804daf3SBarry Smith #include <petscdraw.h> 790971522cSBarry Smith #undef __FUNCT__ 800971522cSBarry Smith #define __FUNCT__ "PCView_FieldSplit" 810971522cSBarry Smith static PetscErrorCode PCView_FieldSplit(PC pc,PetscViewer viewer) 820971522cSBarry Smith { 830971522cSBarry Smith PC_FieldSplit *jac = (PC_FieldSplit*)pc->data; 840971522cSBarry Smith PetscErrorCode ierr; 85d9884438SBarry Smith PetscBool iascii,isdraw; 860971522cSBarry Smith PetscInt i,j; 875a9f2f41SSatish Balay PC_FieldSplitLink ilink = jac->head; 880971522cSBarry Smith 890971522cSBarry Smith PetscFunctionBegin; 90251f4c67SDmitry Karpeev ierr = PetscObjectTypeCompare((PetscObject)viewer,PETSCVIEWERASCII,&iascii);CHKERRQ(ierr); 91d9884438SBarry Smith ierr = PetscObjectTypeCompare((PetscObject)viewer,PETSCVIEWERDRAW,&isdraw);CHKERRQ(ierr); 920971522cSBarry Smith if (iascii) { 932c9966d7SBarry Smith if (jac->bs > 0) { 9451f519a2SBarry Smith ierr = PetscViewerASCIIPrintf(viewer," FieldSplit with %s composition: total splits = %D, blocksize = %D\n",PCCompositeTypes[jac->type],jac->nsplits,jac->bs);CHKERRQ(ierr); 952c9966d7SBarry Smith } else { 962c9966d7SBarry Smith ierr = PetscViewerASCIIPrintf(viewer," FieldSplit with %s composition: total splits = %D\n",PCCompositeTypes[jac->type],jac->nsplits);CHKERRQ(ierr); 972c9966d7SBarry Smith } 98f5236f50SJed Brown if (pc->useAmat) { 99f5236f50SJed Brown ierr = PetscViewerASCIIPrintf(viewer," using Amat (not Pmat) as operator for blocks\n");CHKERRQ(ierr); 100a3df900dSMatthew G Knepley } 10169a612a9SBarry Smith ierr = PetscViewerASCIIPrintf(viewer," Solver info for each split is in the following KSP objects:\n");CHKERRQ(ierr); 1020971522cSBarry Smith ierr = PetscViewerASCIIPushTab(viewer);CHKERRQ(ierr); 1030971522cSBarry Smith for (i=0; i<jac->nsplits; i++) { 1041ab39975SBarry Smith if (ilink->fields) { 1050971522cSBarry Smith ierr = PetscViewerASCIIPrintf(viewer,"Split number %D Fields ",i);CHKERRQ(ierr); 10679416396SBarry Smith ierr = PetscViewerASCIIUseTabs(viewer,PETSC_FALSE);CHKERRQ(ierr); 1075a9f2f41SSatish Balay for (j=0; j<ilink->nfields; j++) { 10879416396SBarry Smith if (j > 0) { 10979416396SBarry Smith ierr = PetscViewerASCIIPrintf(viewer,",");CHKERRQ(ierr); 11079416396SBarry Smith } 1115a9f2f41SSatish Balay ierr = PetscViewerASCIIPrintf(viewer," %D",ilink->fields[j]);CHKERRQ(ierr); 1120971522cSBarry Smith } 1130971522cSBarry Smith ierr = PetscViewerASCIIPrintf(viewer,"\n");CHKERRQ(ierr); 11479416396SBarry Smith ierr = PetscViewerASCIIUseTabs(viewer,PETSC_TRUE);CHKERRQ(ierr); 1151ab39975SBarry Smith } else { 1161ab39975SBarry Smith ierr = PetscViewerASCIIPrintf(viewer,"Split number %D Defined by IS\n",i);CHKERRQ(ierr); 1171ab39975SBarry Smith } 1185a9f2f41SSatish Balay ierr = KSPView(ilink->ksp,viewer);CHKERRQ(ierr); 1195a9f2f41SSatish Balay ilink = ilink->next; 1200971522cSBarry Smith } 1210971522cSBarry Smith ierr = PetscViewerASCIIPopTab(viewer);CHKERRQ(ierr); 1222fa5cd67SKarl Rupp } 1232fa5cd67SKarl Rupp 1242fa5cd67SKarl Rupp if (isdraw) { 125d9884438SBarry Smith PetscDraw draw; 126d9884438SBarry Smith PetscReal x,y,w,wd; 127d9884438SBarry Smith 128d9884438SBarry Smith ierr = PetscViewerDrawGetDraw(viewer,0,&draw);CHKERRQ(ierr); 129d9884438SBarry Smith ierr = PetscDrawGetCurrentPoint(draw,&x,&y);CHKERRQ(ierr); 130d9884438SBarry Smith w = 2*PetscMin(1.0 - x,x); 131d9884438SBarry Smith wd = w/(jac->nsplits + 1); 132d9884438SBarry Smith x = x - wd*(jac->nsplits-1)/2.0; 133d9884438SBarry Smith for (i=0; i<jac->nsplits; i++) { 134d9884438SBarry Smith ierr = PetscDrawPushCurrentPoint(draw,x,y);CHKERRQ(ierr); 135d9884438SBarry Smith ierr = KSPView(ilink->ksp,viewer);CHKERRQ(ierr); 136d9884438SBarry Smith ierr = PetscDrawPopCurrentPoint(draw);CHKERRQ(ierr); 137d9884438SBarry Smith x += wd; 138d9884438SBarry Smith ilink = ilink->next; 139d9884438SBarry Smith } 1400971522cSBarry Smith } 1410971522cSBarry Smith PetscFunctionReturn(0); 1420971522cSBarry Smith } 1430971522cSBarry Smith 1440971522cSBarry Smith #undef __FUNCT__ 1453b224e63SBarry Smith #define __FUNCT__ "PCView_FieldSplit_Schur" 1463b224e63SBarry Smith static PetscErrorCode PCView_FieldSplit_Schur(PC pc,PetscViewer viewer) 1473b224e63SBarry Smith { 1483b224e63SBarry Smith PC_FieldSplit *jac = (PC_FieldSplit*)pc->data; 1493b224e63SBarry Smith PetscErrorCode ierr; 1504996c5bdSBarry Smith PetscBool iascii,isdraw; 1513b224e63SBarry Smith PetscInt i,j; 1523b224e63SBarry Smith PC_FieldSplitLink ilink = jac->head; 1533b224e63SBarry Smith 1543b224e63SBarry Smith PetscFunctionBegin; 155251f4c67SDmitry Karpeev ierr = PetscObjectTypeCompare((PetscObject)viewer,PETSCVIEWERASCII,&iascii);CHKERRQ(ierr); 1564996c5bdSBarry Smith ierr = PetscObjectTypeCompare((PetscObject)viewer,PETSCVIEWERDRAW,&isdraw);CHKERRQ(ierr); 1573b224e63SBarry Smith if (iascii) { 1582c9966d7SBarry Smith if (jac->bs > 0) { 159c9c6ffaaSJed Brown ierr = PetscViewerASCIIPrintf(viewer," FieldSplit with Schur preconditioner, blocksize = %D, factorization %s\n",jac->bs,PCFieldSplitSchurFactTypes[jac->schurfactorization]);CHKERRQ(ierr); 1602c9966d7SBarry Smith } else { 1612c9966d7SBarry Smith ierr = PetscViewerASCIIPrintf(viewer," FieldSplit with Schur preconditioner, factorization %s\n",PCFieldSplitSchurFactTypes[jac->schurfactorization]);CHKERRQ(ierr); 1622c9966d7SBarry Smith } 163f5236f50SJed Brown if (pc->useAmat) { 164f5236f50SJed Brown ierr = PetscViewerASCIIPrintf(viewer," using Amat (not Pmat) as operator for blocks\n");CHKERRQ(ierr); 165a3df900dSMatthew G Knepley } 1663e8b8b31SMatthew G Knepley switch (jac->schurpre) { 1673e8b8b31SMatthew G Knepley case PC_FIELDSPLIT_SCHUR_PRE_SELF: 1683e8b8b31SMatthew G Knepley ierr = PetscViewerASCIIPrintf(viewer," Preconditioner for the Schur complement formed from S itself\n");CHKERRQ(ierr);break; 169a7476a74SDmitry Karpeev case PC_FIELDSPLIT_SCHUR_PRE_SELFP: 170a7476a74SDmitry Karpeev ierr = PetscViewerASCIIPrintf(viewer," Preconditioner for the Schur complement formed from Sp, an assembled approximation to S, which uses A00's diagonal's inverse\n");CHKERRQ(ierr);break; 171e87fab1bSBarry Smith case PC_FIELDSPLIT_SCHUR_PRE_A11: 172e87fab1bSBarry Smith ierr = PetscViewerASCIIPrintf(viewer," Preconditioner for the Schur complement formed from A11\n");CHKERRQ(ierr);break; 1733e8b8b31SMatthew G Knepley case PC_FIELDSPLIT_SCHUR_PRE_USER: 1743e8b8b31SMatthew G Knepley if (jac->schur_user) { 1753e8b8b31SMatthew G Knepley ierr = PetscViewerASCIIPrintf(viewer," Preconditioner for the Schur complement formed from user provided matrix\n");CHKERRQ(ierr); 1763e8b8b31SMatthew G Knepley } else { 177e87fab1bSBarry Smith ierr = PetscViewerASCIIPrintf(viewer," Preconditioner for the Schur complement formed from A11\n");CHKERRQ(ierr); 1783e8b8b31SMatthew G Knepley } 1793e8b8b31SMatthew G Knepley break; 1803e8b8b31SMatthew G Knepley default: 18182f516ccSBarry Smith SETERRQ1(PetscObjectComm((PetscObject)pc), PETSC_ERR_ARG_OUTOFRANGE, "Invalid Schur preconditioning type: %d", jac->schurpre); 1823e8b8b31SMatthew G Knepley } 1833b224e63SBarry Smith ierr = PetscViewerASCIIPrintf(viewer," Split info:\n");CHKERRQ(ierr); 1843b224e63SBarry Smith ierr = PetscViewerASCIIPushTab(viewer);CHKERRQ(ierr); 1853b224e63SBarry Smith for (i=0; i<jac->nsplits; i++) { 1863b224e63SBarry Smith if (ilink->fields) { 1873b224e63SBarry Smith ierr = PetscViewerASCIIPrintf(viewer,"Split number %D Fields ",i);CHKERRQ(ierr); 1883b224e63SBarry Smith ierr = PetscViewerASCIIUseTabs(viewer,PETSC_FALSE);CHKERRQ(ierr); 1893b224e63SBarry Smith for (j=0; j<ilink->nfields; j++) { 1903b224e63SBarry Smith if (j > 0) { 1913b224e63SBarry Smith ierr = PetscViewerASCIIPrintf(viewer,",");CHKERRQ(ierr); 1923b224e63SBarry Smith } 1933b224e63SBarry Smith ierr = PetscViewerASCIIPrintf(viewer," %D",ilink->fields[j]);CHKERRQ(ierr); 1943b224e63SBarry Smith } 1953b224e63SBarry Smith ierr = PetscViewerASCIIPrintf(viewer,"\n");CHKERRQ(ierr); 1963b224e63SBarry Smith ierr = PetscViewerASCIIUseTabs(viewer,PETSC_TRUE);CHKERRQ(ierr); 1973b224e63SBarry Smith } else { 1983b224e63SBarry Smith ierr = PetscViewerASCIIPrintf(viewer,"Split number %D Defined by IS\n",i);CHKERRQ(ierr); 1993b224e63SBarry Smith } 2003b224e63SBarry Smith ilink = ilink->next; 2013b224e63SBarry Smith } 202435f959eSBarry Smith ierr = PetscViewerASCIIPrintf(viewer,"KSP solver for A00 block \n");CHKERRQ(ierr); 2033b224e63SBarry Smith ierr = PetscViewerASCIIPushTab(viewer);CHKERRQ(ierr); 204443836d0SMatthew G Knepley ierr = KSPView(jac->head->ksp,viewer);CHKERRQ(ierr); 2053b224e63SBarry Smith ierr = PetscViewerASCIIPopTab(viewer);CHKERRQ(ierr); 206443836d0SMatthew G Knepley if (jac->kspupper != jac->head->ksp) { 207443836d0SMatthew G Knepley ierr = PetscViewerASCIIPrintf(viewer,"KSP solver for upper A00 in upper triangular factor \n");CHKERRQ(ierr); 208443836d0SMatthew G Knepley ierr = PetscViewerASCIIPushTab(viewer);CHKERRQ(ierr); 209b2750c55SJed Brown if (jac->kspupper) {ierr = KSPView(jac->kspupper,viewer);CHKERRQ(ierr);} 210b2750c55SJed Brown else {ierr = PetscViewerASCIIPrintf(viewer," not yet available\n");CHKERRQ(ierr);} 211443836d0SMatthew G Knepley ierr = PetscViewerASCIIPopTab(viewer);CHKERRQ(ierr); 212443836d0SMatthew G Knepley } 213435f959eSBarry Smith ierr = PetscViewerASCIIPrintf(viewer,"KSP solver for S = A11 - A10 inv(A00) A01 \n");CHKERRQ(ierr); 2143b224e63SBarry Smith ierr = PetscViewerASCIIPushTab(viewer);CHKERRQ(ierr); 21512cae6f2SJed Brown if (jac->kspschur) { 2163b224e63SBarry Smith ierr = KSPView(jac->kspschur,viewer);CHKERRQ(ierr); 21712cae6f2SJed Brown } else { 21812cae6f2SJed Brown ierr = PetscViewerASCIIPrintf(viewer," not yet available\n");CHKERRQ(ierr); 21912cae6f2SJed Brown } 2203b224e63SBarry Smith ierr = PetscViewerASCIIPopTab(viewer);CHKERRQ(ierr); 2213b224e63SBarry Smith ierr = PetscViewerASCIIPopTab(viewer);CHKERRQ(ierr); 2224996c5bdSBarry Smith } else if (isdraw) { 2234996c5bdSBarry Smith PetscDraw draw; 2244996c5bdSBarry Smith PetscReal x,y,w,wd,h; 2254996c5bdSBarry Smith PetscInt cnt = 2; 2264996c5bdSBarry Smith char str[32]; 2274996c5bdSBarry Smith 2284996c5bdSBarry Smith ierr = PetscViewerDrawGetDraw(viewer,0,&draw);CHKERRQ(ierr); 2294996c5bdSBarry Smith ierr = PetscDrawGetCurrentPoint(draw,&x,&y);CHKERRQ(ierr); 230c74581afSBarry Smith if (jac->kspupper != jac->head->ksp) cnt++; 231c74581afSBarry Smith w = 2*PetscMin(1.0 - x,x); 232c74581afSBarry Smith wd = w/(cnt + 1); 233c74581afSBarry Smith 2344996c5bdSBarry Smith ierr = PetscSNPrintf(str,32,"Schur fact. %s",PCFieldSplitSchurFactTypes[jac->schurfactorization]);CHKERRQ(ierr); 2350298fd71SBarry Smith ierr = PetscDrawBoxedString(draw,x,y,PETSC_DRAW_RED,PETSC_DRAW_BLACK,str,NULL,&h);CHKERRQ(ierr); 2364996c5bdSBarry Smith y -= h; 2374996c5bdSBarry Smith if (jac->schurpre == PC_FIELDSPLIT_SCHUR_PRE_USER && !jac->schur_user) { 238e87fab1bSBarry Smith ierr = PetscSNPrintf(str,32,"Prec. for Schur from %s",PCFieldSplitSchurPreTypes[PC_FIELDSPLIT_SCHUR_PRE_A11]);CHKERRQ(ierr); 2393b224e63SBarry Smith } else { 2404996c5bdSBarry Smith ierr = PetscSNPrintf(str,32,"Prec. for Schur from %s",PCFieldSplitSchurPreTypes[jac->schurpre]);CHKERRQ(ierr); 2414996c5bdSBarry Smith } 2420298fd71SBarry Smith ierr = PetscDrawBoxedString(draw,x+wd*(cnt-1)/2.0,y,PETSC_DRAW_RED,PETSC_DRAW_BLACK,str,NULL,&h);CHKERRQ(ierr); 2434996c5bdSBarry Smith y -= h; 2444996c5bdSBarry Smith x = x - wd*(cnt-1)/2.0; 2454996c5bdSBarry Smith 2464996c5bdSBarry Smith ierr = PetscDrawPushCurrentPoint(draw,x,y);CHKERRQ(ierr); 2474996c5bdSBarry Smith ierr = KSPView(jac->head->ksp,viewer);CHKERRQ(ierr); 2484996c5bdSBarry Smith ierr = PetscDrawPopCurrentPoint(draw);CHKERRQ(ierr); 2494996c5bdSBarry Smith if (jac->kspupper != jac->head->ksp) { 2504996c5bdSBarry Smith x += wd; 2514996c5bdSBarry Smith ierr = PetscDrawPushCurrentPoint(draw,x,y);CHKERRQ(ierr); 2524996c5bdSBarry Smith ierr = KSPView(jac->kspupper,viewer);CHKERRQ(ierr); 2534996c5bdSBarry Smith ierr = PetscDrawPopCurrentPoint(draw);CHKERRQ(ierr); 2544996c5bdSBarry Smith } 2554996c5bdSBarry Smith x += wd; 2564996c5bdSBarry Smith ierr = PetscDrawPushCurrentPoint(draw,x,y);CHKERRQ(ierr); 2574996c5bdSBarry Smith ierr = KSPView(jac->kspschur,viewer);CHKERRQ(ierr); 2584996c5bdSBarry Smith ierr = PetscDrawPopCurrentPoint(draw);CHKERRQ(ierr); 2593b224e63SBarry Smith } 2603b224e63SBarry Smith PetscFunctionReturn(0); 2613b224e63SBarry Smith } 2623b224e63SBarry Smith 2633b224e63SBarry Smith #undef __FUNCT__ 2646c924f48SJed Brown #define __FUNCT__ "PCFieldSplitSetRuntimeSplits_Private" 2656c924f48SJed Brown /* Precondition: jac->bs is set to a meaningful value */ 2666c924f48SJed Brown static PetscErrorCode PCFieldSplitSetRuntimeSplits_Private(PC pc) 2676c924f48SJed Brown { 2686c924f48SJed Brown PetscErrorCode ierr; 2696c924f48SJed Brown PC_FieldSplit *jac = (PC_FieldSplit*)pc->data; 2705d4c12cdSJungho Lee PetscInt i,nfields,*ifields,nfields_col,*ifields_col; 2715d4c12cdSJungho Lee PetscBool flg,flg_col; 2725d4c12cdSJungho Lee char optionname[128],splitname[8],optionname_col[128]; 2736c924f48SJed Brown 2746c924f48SJed Brown PetscFunctionBegin; 275785e854fSJed Brown ierr = PetscMalloc1(jac->bs,&ifields);CHKERRQ(ierr); 276785e854fSJed Brown ierr = PetscMalloc1(jac->bs,&ifields_col);CHKERRQ(ierr); 2776c924f48SJed Brown for (i=0,flg=PETSC_TRUE;; i++) { 2788caf3d72SBarry Smith ierr = PetscSNPrintf(splitname,sizeof(splitname),"%D",i);CHKERRQ(ierr); 2798caf3d72SBarry Smith ierr = PetscSNPrintf(optionname,sizeof(optionname),"-pc_fieldsplit_%D_fields",i);CHKERRQ(ierr); 2808caf3d72SBarry Smith ierr = PetscSNPrintf(optionname_col,sizeof(optionname_col),"-pc_fieldsplit_%D_fields_col",i);CHKERRQ(ierr); 2816c924f48SJed Brown nfields = jac->bs; 28229499fbbSJungho Lee nfields_col = jac->bs; 2836c924f48SJed Brown ierr = PetscOptionsGetIntArray(((PetscObject)pc)->prefix,optionname,ifields,&nfields,&flg);CHKERRQ(ierr); 2845d4c12cdSJungho Lee ierr = PetscOptionsGetIntArray(((PetscObject)pc)->prefix,optionname_col,ifields_col,&nfields_col,&flg_col);CHKERRQ(ierr); 2856c924f48SJed Brown if (!flg) break; 2865d4c12cdSJungho Lee else if (flg && !flg_col) { 2875d4c12cdSJungho Lee if (!nfields) SETERRQ(PETSC_COMM_SELF,PETSC_ERR_USER,"Cannot list zero fields"); 2885d4c12cdSJungho Lee ierr = PCFieldSplitSetFields(pc,splitname,nfields,ifields,ifields);CHKERRQ(ierr); 2892fa5cd67SKarl Rupp } else { 2905d4c12cdSJungho Lee if (!nfields || !nfields_col) SETERRQ(PETSC_COMM_SELF,PETSC_ERR_USER,"Cannot list zero fields"); 2915d4c12cdSJungho Lee if (nfields != nfields_col) SETERRQ(PETSC_COMM_SELF,PETSC_ERR_USER,"Number of row and column fields must match"); 2925d4c12cdSJungho Lee ierr = PCFieldSplitSetFields(pc,splitname,nfields,ifields,ifields_col);CHKERRQ(ierr); 2935d4c12cdSJungho Lee } 2946c924f48SJed Brown } 2956c924f48SJed Brown if (i > 0) { 2966c924f48SJed Brown /* Makes command-line setting of splits take precedence over setting them in code. 2976c924f48SJed Brown Otherwise subsequent calls to PCFieldSplitSetIS() or PCFieldSplitSetFields() would 2986c924f48SJed Brown create new splits, which would probably not be what the user wanted. */ 2996c924f48SJed Brown jac->splitdefined = PETSC_TRUE; 3006c924f48SJed Brown } 3016c924f48SJed Brown ierr = PetscFree(ifields);CHKERRQ(ierr); 3025d4c12cdSJungho Lee ierr = PetscFree(ifields_col);CHKERRQ(ierr); 3036c924f48SJed Brown PetscFunctionReturn(0); 3046c924f48SJed Brown } 3056c924f48SJed Brown 3066c924f48SJed Brown #undef __FUNCT__ 30769a612a9SBarry Smith #define __FUNCT__ "PCFieldSplitSetDefaults" 30869a612a9SBarry Smith static PetscErrorCode PCFieldSplitSetDefaults(PC pc) 3090971522cSBarry Smith { 3100971522cSBarry Smith PC_FieldSplit *jac = (PC_FieldSplit*)pc->data; 3110971522cSBarry Smith PetscErrorCode ierr; 3125a9f2f41SSatish Balay PC_FieldSplitLink ilink = jac->head; 3137287d2a3SDmitry Karpeev PetscBool fieldsplit_default = PETSC_FALSE,stokes = PETSC_FALSE; 3146c924f48SJed Brown PetscInt i; 3150971522cSBarry Smith 3160971522cSBarry Smith PetscFunctionBegin; 3177287d2a3SDmitry Karpeev /* 3187287d2a3SDmitry Karpeev Kinda messy, but at least this now uses DMCreateFieldDecomposition() even with jac->reset. 3197287d2a3SDmitry Karpeev Should probably be rewritten. 3207287d2a3SDmitry Karpeev */ 3217287d2a3SDmitry Karpeev if (!ilink || jac->reset) { 3220298fd71SBarry Smith ierr = PetscOptionsGetBool(((PetscObject)pc)->prefix,"-pc_fieldsplit_detect_saddle_point",&stokes,NULL);CHKERRQ(ierr); 3234ab8060aSDmitry Karpeev if (pc->dm && jac->dm_splits && !stokes) { 324bafc1b83SMatthew G Knepley PetscInt numFields, f, i, j; 3250784a22cSJed Brown char **fieldNames; 3267b62db95SJungho Lee IS *fields; 327e7c4fc90SDmitry Karpeev DM *dms; 328bafc1b83SMatthew G Knepley DM subdm[128]; 329bafc1b83SMatthew G Knepley PetscBool flg; 330bafc1b83SMatthew G Knepley 33116621825SDmitry Karpeev ierr = DMCreateFieldDecomposition(pc->dm, &numFields, &fieldNames, &fields, &dms);CHKERRQ(ierr); 332bafc1b83SMatthew G Knepley /* Allow the user to prescribe the splits */ 333bafc1b83SMatthew G Knepley for (i = 0, flg = PETSC_TRUE;; i++) { 334bafc1b83SMatthew G Knepley PetscInt ifields[128]; 335bafc1b83SMatthew G Knepley IS compField; 336bafc1b83SMatthew G Knepley char optionname[128], splitname[8]; 337bafc1b83SMatthew G Knepley PetscInt nfields = numFields; 338bafc1b83SMatthew G Knepley 3398caf3d72SBarry Smith ierr = PetscSNPrintf(optionname, sizeof(optionname), "-pc_fieldsplit_%D_fields", i);CHKERRQ(ierr); 340bafc1b83SMatthew G Knepley ierr = PetscOptionsGetIntArray(((PetscObject) pc)->prefix, optionname, ifields, &nfields, &flg);CHKERRQ(ierr); 341bafc1b83SMatthew G Knepley if (!flg) break; 34282f516ccSBarry Smith if (numFields > 128) SETERRQ1(PetscObjectComm((PetscObject)pc),PETSC_ERR_SUP,"Cannot currently support %d > 128 fields", numFields); 343bafc1b83SMatthew G Knepley ierr = DMCreateSubDM(pc->dm, nfields, ifields, &compField, &subdm[i]);CHKERRQ(ierr); 344bafc1b83SMatthew G Knepley if (nfields == 1) { 345bafc1b83SMatthew G Knepley ierr = PCFieldSplitSetIS(pc, fieldNames[ifields[0]], compField);CHKERRQ(ierr); 34682f516ccSBarry Smith /* ierr = PetscPrintf(PetscObjectComm((PetscObject)pc), "%s Field Indices:", fieldNames[ifields[0]]);CHKERRQ(ierr); 3470298fd71SBarry Smith ierr = ISView(compField, NULL);CHKERRQ(ierr); */ 348bafc1b83SMatthew G Knepley } else { 3498caf3d72SBarry Smith ierr = PetscSNPrintf(splitname, sizeof(splitname), "%D", i);CHKERRQ(ierr); 350bafc1b83SMatthew G Knepley ierr = PCFieldSplitSetIS(pc, splitname, compField);CHKERRQ(ierr); 35182f516ccSBarry Smith /* ierr = PetscPrintf(PetscObjectComm((PetscObject)pc), "%s Field Indices:", splitname);CHKERRQ(ierr); 3520298fd71SBarry Smith ierr = ISView(compField, NULL);CHKERRQ(ierr); */ 3537287d2a3SDmitry Karpeev } 354bafc1b83SMatthew G Knepley ierr = ISDestroy(&compField);CHKERRQ(ierr); 355bafc1b83SMatthew G Knepley for (j = 0; j < nfields; ++j) { 356bafc1b83SMatthew G Knepley f = ifields[j]; 3577b62db95SJungho Lee ierr = PetscFree(fieldNames[f]);CHKERRQ(ierr); 3587b62db95SJungho Lee ierr = ISDestroy(&fields[f]);CHKERRQ(ierr); 3597b62db95SJungho Lee } 360bafc1b83SMatthew G Knepley } 361bafc1b83SMatthew G Knepley if (i == 0) { 362bafc1b83SMatthew G Knepley for (f = 0; f < numFields; ++f) { 363bafc1b83SMatthew G Knepley ierr = PCFieldSplitSetIS(pc, fieldNames[f], fields[f]);CHKERRQ(ierr); 364bafc1b83SMatthew G Knepley ierr = PetscFree(fieldNames[f]);CHKERRQ(ierr); 365bafc1b83SMatthew G Knepley ierr = ISDestroy(&fields[f]);CHKERRQ(ierr); 366bafc1b83SMatthew G Knepley } 367bafc1b83SMatthew G Knepley } else { 368d724dfffSBarry Smith for (j=0; j<numFields; j++) { 369d724dfffSBarry Smith ierr = DMDestroy(dms+j);CHKERRQ(ierr); 370d724dfffSBarry Smith } 371d724dfffSBarry Smith ierr = PetscFree(dms);CHKERRQ(ierr); 372785e854fSJed Brown ierr = PetscMalloc1(i, &dms);CHKERRQ(ierr); 3732fa5cd67SKarl Rupp for (j = 0; j < i; ++j) dms[j] = subdm[j]; 374bafc1b83SMatthew G Knepley } 3757b62db95SJungho Lee ierr = PetscFree(fieldNames);CHKERRQ(ierr); 3767b62db95SJungho Lee ierr = PetscFree(fields);CHKERRQ(ierr); 377e7c4fc90SDmitry Karpeev if (dms) { 3788b8307b2SJed Brown ierr = PetscInfo(pc, "Setting up physics based fieldsplit preconditioner using the embedded DM\n");CHKERRQ(ierr); 379bafc1b83SMatthew G Knepley for (ilink = jac->head, i = 0; ilink; ilink = ilink->next, ++i) { 3807287d2a3SDmitry Karpeev const char *prefix; 3817287d2a3SDmitry Karpeev ierr = PetscObjectGetOptionsPrefix((PetscObject)(ilink->ksp),&prefix);CHKERRQ(ierr); 3827287d2a3SDmitry Karpeev ierr = PetscObjectSetOptionsPrefix((PetscObject)(dms[i]), prefix);CHKERRQ(ierr); 3837b62db95SJungho Lee ierr = KSPSetDM(ilink->ksp, dms[i]);CHKERRQ(ierr); 3847b62db95SJungho Lee ierr = KSPSetDMActive(ilink->ksp, PETSC_FALSE);CHKERRQ(ierr); 3857287d2a3SDmitry Karpeev ierr = PetscObjectIncrementTabLevel((PetscObject)dms[i],(PetscObject)ilink->ksp,0);CHKERRQ(ierr); 386e7c4fc90SDmitry Karpeev ierr = DMDestroy(&dms[i]);CHKERRQ(ierr); 3872fa5ba8aSJed Brown } 3887b62db95SJungho Lee ierr = PetscFree(dms);CHKERRQ(ierr); 3898b8307b2SJed Brown } 39066ffff09SJed Brown } else { 391521d7252SBarry Smith if (jac->bs <= 0) { 392704ba839SBarry Smith if (pc->pmat) { 393521d7252SBarry Smith ierr = MatGetBlockSize(pc->pmat,&jac->bs);CHKERRQ(ierr); 3942fa5cd67SKarl Rupp } else jac->bs = 1; 395521d7252SBarry Smith } 396d32f9abdSBarry Smith 3976ce1633cSBarry Smith if (stokes) { 3986ce1633cSBarry Smith IS zerodiags,rest; 3996ce1633cSBarry Smith PetscInt nmin,nmax; 4006ce1633cSBarry Smith 4016ce1633cSBarry Smith ierr = MatGetOwnershipRange(pc->mat,&nmin,&nmax);CHKERRQ(ierr); 4026ce1633cSBarry Smith ierr = MatFindZeroDiagonals(pc->mat,&zerodiags);CHKERRQ(ierr); 4036ce1633cSBarry Smith ierr = ISComplement(zerodiags,nmin,nmax,&rest);CHKERRQ(ierr); 4047287d2a3SDmitry Karpeev if (jac->reset) { 4057287d2a3SDmitry Karpeev jac->head->is = rest; 4067287d2a3SDmitry Karpeev jac->head->next->is = zerodiags; 4072fa5cd67SKarl Rupp } else { 4086ce1633cSBarry Smith ierr = PCFieldSplitSetIS(pc,"0",rest);CHKERRQ(ierr); 4096ce1633cSBarry Smith ierr = PCFieldSplitSetIS(pc,"1",zerodiags);CHKERRQ(ierr); 4107287d2a3SDmitry Karpeev } 411fcfd50ebSBarry Smith ierr = ISDestroy(&zerodiags);CHKERRQ(ierr); 412fcfd50ebSBarry Smith ierr = ISDestroy(&rest);CHKERRQ(ierr); 4136ce1633cSBarry Smith } else { 414ce94432eSBarry Smith if (jac->reset) SETERRQ(PetscObjectComm((PetscObject)pc),PETSC_ERR_SUP,"Cases not yet handled when PCReset() was used"); 4159eeaaa73SJed Brown ierr = PetscOptionsGetBool(((PetscObject)pc)->prefix,"-pc_fieldsplit_default",&fieldsplit_default,NULL);CHKERRQ(ierr); 4167287d2a3SDmitry Karpeev if (!fieldsplit_default) { 417d32f9abdSBarry Smith /* Allow user to set fields from command line, if bs was known at the time of PCSetFromOptions_FieldSplit() 418d32f9abdSBarry Smith then it is set there. This is not ideal because we should only have options set in XXSetFromOptions(). */ 4196c924f48SJed Brown ierr = PCFieldSplitSetRuntimeSplits_Private(pc);CHKERRQ(ierr); 4206c924f48SJed Brown if (jac->splitdefined) {ierr = PetscInfo(pc,"Splits defined using the options database\n");CHKERRQ(ierr);} 421d32f9abdSBarry Smith } 4227287d2a3SDmitry Karpeev if (fieldsplit_default || !jac->splitdefined) { 423d32f9abdSBarry Smith ierr = PetscInfo(pc,"Using default splitting of fields\n");CHKERRQ(ierr); 424db4c96c1SJed Brown for (i=0; i<jac->bs; i++) { 4256c924f48SJed Brown char splitname[8]; 4268caf3d72SBarry Smith ierr = PetscSNPrintf(splitname,sizeof(splitname),"%D",i);CHKERRQ(ierr); 4275d4c12cdSJungho Lee ierr = PCFieldSplitSetFields(pc,splitname,1,&i,&i);CHKERRQ(ierr); 42879416396SBarry Smith } 4295d4c12cdSJungho Lee jac->defaultsplit = PETSC_TRUE; 430521d7252SBarry Smith } 43166ffff09SJed Brown } 4326ce1633cSBarry Smith } 433edf189efSBarry Smith } else if (jac->nsplits == 1) { 434edf189efSBarry Smith if (ilink->is) { 435edf189efSBarry Smith IS is2; 436edf189efSBarry Smith PetscInt nmin,nmax; 437edf189efSBarry Smith 438edf189efSBarry Smith ierr = MatGetOwnershipRange(pc->mat,&nmin,&nmax);CHKERRQ(ierr); 439edf189efSBarry Smith ierr = ISComplement(ilink->is,nmin,nmax,&is2);CHKERRQ(ierr); 440db4c96c1SJed Brown ierr = PCFieldSplitSetIS(pc,"1",is2);CHKERRQ(ierr); 441fcfd50ebSBarry Smith ierr = ISDestroy(&is2);CHKERRQ(ierr); 44282f516ccSBarry Smith } else SETERRQ(PetscObjectComm((PetscObject)pc),PETSC_ERR_SUP,"Must provide at least two sets of fields to PCFieldSplit()"); 443edf189efSBarry Smith } 444d0af7cd3SBarry Smith 445d0af7cd3SBarry Smith 44682f516ccSBarry Smith if (jac->nsplits < 2) SETERRQ1(PetscObjectComm((PetscObject)pc),PETSC_ERR_PLIB,"Unhandled case, must have at least two fields, not %d", jac->nsplits); 44769a612a9SBarry Smith PetscFunctionReturn(0); 44869a612a9SBarry Smith } 44969a612a9SBarry Smith 4505a576424SJed Brown PETSC_EXTERN PetscErrorCode PetscOptionsFindPairPrefix_Private(const char pre[], const char name[], char *value[], PetscBool *flg); 451514bf10dSMatthew G Knepley 45269a612a9SBarry Smith #undef __FUNCT__ 45369a612a9SBarry Smith #define __FUNCT__ "PCSetUp_FieldSplit" 45469a612a9SBarry Smith static PetscErrorCode PCSetUp_FieldSplit(PC pc) 45569a612a9SBarry Smith { 45669a612a9SBarry Smith PC_FieldSplit *jac = (PC_FieldSplit*)pc->data; 45769a612a9SBarry Smith PetscErrorCode ierr; 4585a9f2f41SSatish Balay PC_FieldSplitLink ilink; 4592c9966d7SBarry Smith PetscInt i,nsplit; 46069a612a9SBarry Smith MatStructure flag = pc->flag; 4615f4ab4e1SJungho Lee PetscBool sorted, sorted_col; 46269a612a9SBarry Smith 46369a612a9SBarry Smith PetscFunctionBegin; 46469a612a9SBarry Smith ierr = PCFieldSplitSetDefaults(pc);CHKERRQ(ierr); 46597bbdb24SBarry Smith nsplit = jac->nsplits; 4665a9f2f41SSatish Balay ilink = jac->head; 46797bbdb24SBarry Smith 46897bbdb24SBarry Smith /* get the matrices for each split */ 469704ba839SBarry Smith if (!jac->issetup) { 4701b9fc7fcSBarry Smith PetscInt rstart,rend,nslots,bs; 47197bbdb24SBarry Smith 472704ba839SBarry Smith jac->issetup = PETSC_TRUE; 473704ba839SBarry Smith 4745d4c12cdSJungho Lee /* This is done here instead of in PCFieldSplitSetFields() because may not have matrix at that point */ 4752c9966d7SBarry Smith if (jac->defaultsplit || !ilink->is) { 4762c9966d7SBarry Smith if (jac->bs <= 0) jac->bs = nsplit; 4772c9966d7SBarry Smith } 47851f519a2SBarry Smith bs = jac->bs; 47997bbdb24SBarry Smith ierr = MatGetOwnershipRange(pc->pmat,&rstart,&rend);CHKERRQ(ierr); 4801b9fc7fcSBarry Smith nslots = (rend - rstart)/bs; 4811b9fc7fcSBarry Smith for (i=0; i<nsplit; i++) { 4821b9fc7fcSBarry Smith if (jac->defaultsplit) { 483ce94432eSBarry Smith ierr = ISCreateStride(PetscObjectComm((PetscObject)pc),nslots,rstart+i,nsplit,&ilink->is);CHKERRQ(ierr); 4845f4ab4e1SJungho Lee ierr = ISDuplicate(ilink->is,&ilink->is_col);CHKERRQ(ierr); 485704ba839SBarry Smith } else if (!ilink->is) { 486ccb205f8SBarry Smith if (ilink->nfields > 1) { 4875f4ab4e1SJungho Lee PetscInt *ii,*jj,j,k,nfields = ilink->nfields,*fields = ilink->fields,*fields_col = ilink->fields_col; 488785e854fSJed Brown ierr = PetscMalloc1(ilink->nfields*nslots,&ii);CHKERRQ(ierr); 489785e854fSJed Brown ierr = PetscMalloc1(ilink->nfields*nslots,&jj);CHKERRQ(ierr); 4901b9fc7fcSBarry Smith for (j=0; j<nslots; j++) { 4911b9fc7fcSBarry Smith for (k=0; k<nfields; k++) { 4921b9fc7fcSBarry Smith ii[nfields*j + k] = rstart + bs*j + fields[k]; 4935f4ab4e1SJungho Lee jj[nfields*j + k] = rstart + bs*j + fields_col[k]; 49497bbdb24SBarry Smith } 49597bbdb24SBarry Smith } 496ce94432eSBarry Smith ierr = ISCreateGeneral(PetscObjectComm((PetscObject)pc),nslots*nfields,ii,PETSC_OWN_POINTER,&ilink->is);CHKERRQ(ierr); 497ce94432eSBarry Smith ierr = ISCreateGeneral(PetscObjectComm((PetscObject)pc),nslots*nfields,jj,PETSC_OWN_POINTER,&ilink->is_col);CHKERRQ(ierr); 498ccb205f8SBarry Smith } else { 499ce94432eSBarry Smith ierr = ISCreateStride(PetscObjectComm((PetscObject)pc),nslots,rstart+ilink->fields[0],bs,&ilink->is);CHKERRQ(ierr); 500ce94432eSBarry Smith ierr = ISCreateStride(PetscObjectComm((PetscObject)pc),nslots,rstart+ilink->fields_col[0],bs,&ilink->is_col);CHKERRQ(ierr); 501ccb205f8SBarry Smith } 5023e197d65SBarry Smith } 503704ba839SBarry Smith ierr = ISSorted(ilink->is,&sorted);CHKERRQ(ierr); 5045f4ab4e1SJungho Lee if (ilink->is_col) { ierr = ISSorted(ilink->is_col,&sorted_col);CHKERRQ(ierr); } 5055f4ab4e1SJungho Lee if (!sorted || !sorted_col) SETERRQ(PETSC_COMM_SELF,PETSC_ERR_USER,"Fields must be sorted when creating split"); 506704ba839SBarry Smith ilink = ilink->next; 5071b9fc7fcSBarry Smith } 5081b9fc7fcSBarry Smith } 5091b9fc7fcSBarry Smith 510704ba839SBarry Smith ilink = jac->head; 51197bbdb24SBarry Smith if (!jac->pmat) { 512bdddcaaaSMatthew G Knepley Vec xtmp; 513bdddcaaaSMatthew G Knepley 5140298fd71SBarry Smith ierr = MatGetVecs(pc->pmat,&xtmp,NULL);CHKERRQ(ierr); 515785e854fSJed Brown ierr = PetscMalloc1(nsplit,&jac->pmat);CHKERRQ(ierr); 516dcca6d9dSJed Brown ierr = PetscMalloc2(nsplit,&jac->x,nsplit,&jac->y);CHKERRQ(ierr); 517cf502942SBarry Smith for (i=0; i<nsplit; i++) { 518bdddcaaaSMatthew G Knepley MatNullSpace sp; 519bdddcaaaSMatthew G Knepley 520a3df900dSMatthew G Knepley /* Check for preconditioning matrix attached to IS */ 521a3df900dSMatthew G Knepley ierr = PetscObjectQuery((PetscObject) ilink->is, "pmat", (PetscObject*) &jac->pmat[i]);CHKERRQ(ierr); 522a3df900dSMatthew G Knepley if (jac->pmat[i]) { 523a3df900dSMatthew G Knepley ierr = PetscObjectReference((PetscObject) jac->pmat[i]);CHKERRQ(ierr); 524a3df900dSMatthew G Knepley if (jac->type == PC_COMPOSITE_SCHUR) { 525a3df900dSMatthew G Knepley jac->schur_user = jac->pmat[i]; 5262fa5cd67SKarl Rupp 527a3df900dSMatthew G Knepley ierr = PetscObjectReference((PetscObject) jac->schur_user);CHKERRQ(ierr); 528a3df900dSMatthew G Knepley } 529a3df900dSMatthew G Knepley } else { 5305f4ab4e1SJungho Lee ierr = MatGetSubMatrix(pc->pmat,ilink->is,ilink->is_col,MAT_INITIAL_MATRIX,&jac->pmat[i]);CHKERRQ(ierr); 531a3df900dSMatthew G Knepley } 532bdddcaaaSMatthew G Knepley /* create work vectors for each split */ 533bdddcaaaSMatthew G Knepley ierr = MatGetVecs(jac->pmat[i],&jac->x[i],&jac->y[i]);CHKERRQ(ierr); 5340298fd71SBarry Smith ilink->x = jac->x[i]; ilink->y = jac->y[i]; ilink->z = NULL; 535bdddcaaaSMatthew G Knepley /* compute scatter contexts needed by multiplicative versions and non-default splits */ 5360298fd71SBarry Smith ierr = VecScatterCreate(xtmp,ilink->is,jac->x[i],NULL,&ilink->sctx);CHKERRQ(ierr); 537ed1f0337SMatthew G Knepley /* Check for null space attached to IS */ 538bafc1b83SMatthew G Knepley ierr = PetscObjectQuery((PetscObject) ilink->is, "nullspace", (PetscObject*) &sp);CHKERRQ(ierr); 539bafc1b83SMatthew G Knepley if (sp) { 540bafc1b83SMatthew G Knepley ierr = MatSetNullSpace(jac->pmat[i], sp);CHKERRQ(ierr); 541bafc1b83SMatthew G Knepley } 542ed1f0337SMatthew G Knepley ierr = PetscObjectQuery((PetscObject) ilink->is, "nearnullspace", (PetscObject*) &sp);CHKERRQ(ierr); 543ed1f0337SMatthew G Knepley if (sp) { 544ed1f0337SMatthew G Knepley ierr = MatSetNearNullSpace(jac->pmat[i], sp);CHKERRQ(ierr); 545ed1f0337SMatthew G Knepley } 546704ba839SBarry Smith ilink = ilink->next; 547cf502942SBarry Smith } 548bdddcaaaSMatthew G Knepley ierr = VecDestroy(&xtmp);CHKERRQ(ierr); 54997bbdb24SBarry Smith } else { 550cf502942SBarry Smith for (i=0; i<nsplit; i++) { 551a3df900dSMatthew G Knepley Mat pmat; 552a3df900dSMatthew G Knepley 553a3df900dSMatthew G Knepley /* Check for preconditioning matrix attached to IS */ 554a3df900dSMatthew G Knepley ierr = PetscObjectQuery((PetscObject) ilink->is, "pmat", (PetscObject*) &pmat);CHKERRQ(ierr); 555a3df900dSMatthew G Knepley if (!pmat) { 5565f4ab4e1SJungho Lee ierr = MatGetSubMatrix(pc->pmat,ilink->is,ilink->is_col,MAT_REUSE_MATRIX,&jac->pmat[i]);CHKERRQ(ierr); 557a3df900dSMatthew G Knepley } 558704ba839SBarry Smith ilink = ilink->next; 559cf502942SBarry Smith } 56097bbdb24SBarry Smith } 561f5236f50SJed Brown if (pc->useAmat) { 562519d70e2SJed Brown ilink = jac->head; 563519d70e2SJed Brown if (!jac->mat) { 564785e854fSJed Brown ierr = PetscMalloc1(nsplit,&jac->mat);CHKERRQ(ierr); 565519d70e2SJed Brown for (i=0; i<nsplit; i++) { 5665f4ab4e1SJungho Lee ierr = MatGetSubMatrix(pc->mat,ilink->is,ilink->is_col,MAT_INITIAL_MATRIX,&jac->mat[i]);CHKERRQ(ierr); 567519d70e2SJed Brown ilink = ilink->next; 568519d70e2SJed Brown } 569519d70e2SJed Brown } else { 570519d70e2SJed Brown for (i=0; i<nsplit; i++) { 5715f4ab4e1SJungho Lee if (jac->mat[i]) {ierr = MatGetSubMatrix(pc->mat,ilink->is,ilink->is_col,MAT_REUSE_MATRIX,&jac->mat[i]);CHKERRQ(ierr);} 572519d70e2SJed Brown ilink = ilink->next; 573519d70e2SJed Brown } 574519d70e2SJed Brown } 575519d70e2SJed Brown } else { 576519d70e2SJed Brown jac->mat = jac->pmat; 577519d70e2SJed Brown } 57897bbdb24SBarry Smith 5796c8605c2SJed Brown if (jac->type != PC_COMPOSITE_ADDITIVE && jac->type != PC_COMPOSITE_SCHUR) { 58068dd23aaSBarry Smith /* extract the rows of the matrix associated with each field: used for efficient computation of residual inside algorithm */ 58168dd23aaSBarry Smith ilink = jac->head; 58268dd23aaSBarry Smith if (!jac->Afield) { 583785e854fSJed Brown ierr = PetscMalloc1(nsplit,&jac->Afield);CHKERRQ(ierr); 58468dd23aaSBarry Smith for (i=0; i<nsplit; i++) { 5850298fd71SBarry Smith ierr = MatGetSubMatrix(pc->mat,ilink->is,NULL,MAT_INITIAL_MATRIX,&jac->Afield[i]);CHKERRQ(ierr); 58668dd23aaSBarry Smith ilink = ilink->next; 58768dd23aaSBarry Smith } 58868dd23aaSBarry Smith } else { 58968dd23aaSBarry Smith for (i=0; i<nsplit; i++) { 5900298fd71SBarry Smith ierr = MatGetSubMatrix(pc->mat,ilink->is,NULL,MAT_REUSE_MATRIX,&jac->Afield[i]);CHKERRQ(ierr); 59168dd23aaSBarry Smith ilink = ilink->next; 59268dd23aaSBarry Smith } 59368dd23aaSBarry Smith } 59468dd23aaSBarry Smith } 59568dd23aaSBarry Smith 5963b224e63SBarry Smith if (jac->type == PC_COMPOSITE_SCHUR) { 5973b224e63SBarry Smith IS ccis; 5984aa3045dSJed Brown PetscInt rstart,rend; 599093c86ffSJed Brown char lscname[256]; 600093c86ffSJed Brown PetscObject LSC_L; 601ce94432eSBarry Smith 602ce94432eSBarry Smith if (nsplit != 2) SETERRQ(PetscObjectComm((PetscObject)pc),PETSC_ERR_ARG_INCOMP,"To use Schur complement preconditioner you must have exactly 2 fields"); 60368dd23aaSBarry Smith 604e6cab6aaSJed Brown /* When extracting off-diagonal submatrices, we take complements from this range */ 605e6cab6aaSJed Brown ierr = MatGetOwnershipRangeColumn(pc->mat,&rstart,&rend);CHKERRQ(ierr); 606e6cab6aaSJed Brown 6073b224e63SBarry Smith /* need to handle case when one is resetting up the preconditioner */ 6083b224e63SBarry Smith if (jac->schur) { 6090298fd71SBarry Smith KSP kspA = jac->head->ksp, kspInner = NULL, kspUpper = jac->kspupper; 610443836d0SMatthew G Knepley 611fb3147dbSMatthew G Knepley ierr = MatSchurComplementGetKSP(jac->schur, &kspInner);CHKERRQ(ierr); 6123b224e63SBarry Smith ilink = jac->head; 61349bb4cd7SJungho Lee ierr = ISComplement(ilink->is_col,rstart,rend,&ccis);CHKERRQ(ierr); 6144aa3045dSJed Brown ierr = MatGetSubMatrix(pc->mat,ilink->is,ccis,MAT_REUSE_MATRIX,&jac->B);CHKERRQ(ierr); 615fcfd50ebSBarry Smith ierr = ISDestroy(&ccis);CHKERRQ(ierr); 6163b224e63SBarry Smith ilink = ilink->next; 61749bb4cd7SJungho Lee ierr = ISComplement(ilink->is_col,rstart,rend,&ccis);CHKERRQ(ierr); 6184aa3045dSJed Brown ierr = MatGetSubMatrix(pc->mat,ilink->is,ccis,MAT_REUSE_MATRIX,&jac->C);CHKERRQ(ierr); 619fcfd50ebSBarry Smith ierr = ISDestroy(&ccis);CHKERRQ(ierr); 620a3df900dSMatthew G Knepley ierr = MatSchurComplementUpdate(jac->schur,jac->mat[0],jac->pmat[0],jac->B,jac->C,jac->mat[1],pc->flag);CHKERRQ(ierr); 621a7476a74SDmitry Karpeev if (jac->schurpre == PC_FIELDSPLIT_SCHUR_PRE_SELFP) { 622a7476a74SDmitry Karpeev ierr = MatDestroy(&jac->schurp);CHKERRQ(ierr); 623a7476a74SDmitry Karpeev ierr = MatSchurComplementGetPmat(jac->schur,MAT_INITIAL_MATRIX,&jac->schurp);CHKERRQ(ierr); 624a7476a74SDmitry Karpeev } 625443836d0SMatthew G Knepley if (kspA != kspInner) { 626443836d0SMatthew G Knepley ierr = KSPSetOperators(kspA,jac->mat[0],jac->pmat[0],pc->flag);CHKERRQ(ierr); 627443836d0SMatthew G Knepley } 628443836d0SMatthew G Knepley if (kspUpper != kspA) { 629443836d0SMatthew G Knepley ierr = KSPSetOperators(kspUpper,jac->mat[0],jac->pmat[0],pc->flag);CHKERRQ(ierr); 630443836d0SMatthew G Knepley } 631084e4875SJed Brown ierr = KSPSetOperators(jac->kspschur,jac->schur,FieldSplitSchurPre(jac),pc->flag);CHKERRQ(ierr); 6323b224e63SBarry Smith } else { 633bafc1b83SMatthew G Knepley const char *Dprefix; 634bafc1b83SMatthew G Knepley char schurprefix[256]; 635514bf10dSMatthew G Knepley char schurtestoption[256]; 636bdddcaaaSMatthew G Knepley MatNullSpace sp; 637514bf10dSMatthew G Knepley PetscBool flg; 6383b224e63SBarry Smith 639a04f6461SBarry Smith /* extract the A01 and A10 matrices */ 6403b224e63SBarry Smith ilink = jac->head; 64149bb4cd7SJungho Lee ierr = ISComplement(ilink->is_col,rstart,rend,&ccis);CHKERRQ(ierr); 6424aa3045dSJed Brown ierr = MatGetSubMatrix(pc->mat,ilink->is,ccis,MAT_INITIAL_MATRIX,&jac->B);CHKERRQ(ierr); 643fcfd50ebSBarry Smith ierr = ISDestroy(&ccis);CHKERRQ(ierr); 6443b224e63SBarry Smith ilink = ilink->next; 64549bb4cd7SJungho Lee ierr = ISComplement(ilink->is_col,rstart,rend,&ccis);CHKERRQ(ierr); 6464aa3045dSJed Brown ierr = MatGetSubMatrix(pc->mat,ilink->is,ccis,MAT_INITIAL_MATRIX,&jac->C);CHKERRQ(ierr); 647fcfd50ebSBarry Smith ierr = ISDestroy(&ccis);CHKERRQ(ierr); 64820252d06SBarry Smith 649f5236f50SJed Brown /* Use mat[0] (diagonal block of Amat) preconditioned by pmat[0] to define Schur complement */ 65020252d06SBarry Smith ierr = MatCreate(((PetscObject)jac->mat[0])->comm,&jac->schur);CHKERRQ(ierr); 65120252d06SBarry Smith ierr = MatSetType(jac->schur,MATSCHURCOMPLEMENT);CHKERRQ(ierr); 65220252d06SBarry Smith ierr = MatSchurComplementSet(jac->schur,jac->mat[0],jac->pmat[0],jac->B,jac->C,jac->mat[1]);CHKERRQ(ierr); 65320252d06SBarry Smith 654bdddcaaaSMatthew G Knepley ierr = MatGetNullSpace(jac->pmat[1], &sp);CHKERRQ(ierr); 65520252d06SBarry Smith if (sp) { 65620252d06SBarry Smith ierr = MatSetNullSpace(jac->schur, sp);CHKERRQ(ierr); 65720252d06SBarry Smith } 65820252d06SBarry Smith 65920252d06SBarry Smith ierr = PetscSNPrintf(schurtestoption, sizeof(schurtestoption), "-fieldsplit_%s_inner_", ilink->splitname);CHKERRQ(ierr); 6600298fd71SBarry Smith ierr = PetscOptionsFindPairPrefix_Private(((PetscObject)pc)->prefix, schurtestoption, NULL, &flg);CHKERRQ(ierr); 661514bf10dSMatthew G Knepley if (flg) { 662514bf10dSMatthew G Knepley DM dmInner; 66321635b76SJed Brown KSP kspInner; 66421635b76SJed Brown 66521635b76SJed Brown ierr = MatSchurComplementGetKSP(jac->schur, &kspInner);CHKERRQ(ierr); 66621635b76SJed Brown ierr = PetscSNPrintf(schurprefix, sizeof(schurprefix), "%sfieldsplit_%s_inner_", ((PetscObject)pc)->prefix ? ((PetscObject)pc)->prefix : "", ilink->splitname);CHKERRQ(ierr); 66721635b76SJed Brown /* Indent this deeper to emphasize the "inner" nature of this solver. */ 66821635b76SJed Brown ierr = PetscObjectIncrementTabLevel((PetscObject)kspInner, (PetscObject) pc, 2);CHKERRQ(ierr); 66921635b76SJed Brown ierr = KSPSetOptionsPrefix(kspInner, schurprefix);CHKERRQ(ierr); 670514bf10dSMatthew G Knepley 671514bf10dSMatthew G Knepley /* Set DM for new solver */ 672bafc1b83SMatthew G Knepley ierr = KSPGetDM(jac->head->ksp, &dmInner);CHKERRQ(ierr); 67321635b76SJed Brown ierr = KSPSetDM(kspInner, dmInner);CHKERRQ(ierr); 67421635b76SJed Brown ierr = KSPSetDMActive(kspInner, PETSC_FALSE);CHKERRQ(ierr); 675514bf10dSMatthew G Knepley } else { 67621635b76SJed Brown /* Use the outer solver for the inner solve, but revert the KSPPREONLY from PCFieldSplitSetFields_FieldSplit or 67721635b76SJed Brown * PCFieldSplitSetIS_FieldSplit. We don't want KSPPREONLY because it makes the Schur complement inexact, 67821635b76SJed Brown * preventing Schur complement reduction to be an accurate solve. Usually when an iterative solver is used for 67921635b76SJed 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 68021635b76SJed Brown * GMRES the default. Note that it is also common to use PREONLY for S, in which case S may not be used 68121635b76SJed Brown * directly, and the user is responsible for setting an inexact method for fieldsplit's A^{-1}. */ 68221635b76SJed Brown ierr = KSPSetType(jac->head->ksp,KSPGMRES);CHKERRQ(ierr); 683514bf10dSMatthew G Knepley ierr = MatSchurComplementSetKSP(jac->schur,jac->head->ksp);CHKERRQ(ierr); 684bafc1b83SMatthew G Knepley } 6855a9f2f41SSatish Balay ierr = KSPSetOperators(jac->head->ksp,jac->mat[0],jac->pmat[0],flag);CHKERRQ(ierr); 6865a9f2f41SSatish Balay ierr = KSPSetFromOptions(jac->head->ksp);CHKERRQ(ierr); 68797bbdb24SBarry Smith ierr = MatSetFromOptions(jac->schur);CHKERRQ(ierr); 68897bbdb24SBarry Smith 689443836d0SMatthew G Knepley ierr = PetscSNPrintf(schurtestoption, sizeof(schurtestoption), "-fieldsplit_%s_upper_", ilink->splitname);CHKERRQ(ierr); 6900298fd71SBarry Smith ierr = PetscOptionsFindPairPrefix_Private(((PetscObject)pc)->prefix, schurtestoption, NULL, &flg);CHKERRQ(ierr); 691443836d0SMatthew G Knepley if (flg) { 692443836d0SMatthew G Knepley DM dmInner; 693443836d0SMatthew G Knepley 694443836d0SMatthew G Knepley ierr = PetscSNPrintf(schurprefix, sizeof(schurprefix), "%sfieldsplit_%s_upper_", ((PetscObject)pc)->prefix ? ((PetscObject)pc)->prefix : "", ilink->splitname);CHKERRQ(ierr); 69582f516ccSBarry Smith ierr = KSPCreate(PetscObjectComm((PetscObject)pc), &jac->kspupper);CHKERRQ(ierr); 696443836d0SMatthew G Knepley ierr = KSPSetOptionsPrefix(jac->kspupper, schurprefix);CHKERRQ(ierr); 697443836d0SMatthew G Knepley ierr = KSPGetDM(jac->head->ksp, &dmInner);CHKERRQ(ierr); 698443836d0SMatthew G Knepley ierr = KSPSetDM(jac->kspupper, dmInner);CHKERRQ(ierr); 699443836d0SMatthew G Knepley ierr = KSPSetDMActive(jac->kspupper, PETSC_FALSE);CHKERRQ(ierr); 700443836d0SMatthew G Knepley ierr = KSPSetFromOptions(jac->kspupper);CHKERRQ(ierr); 701443836d0SMatthew G Knepley ierr = KSPSetOperators(jac->kspupper,jac->mat[0],jac->pmat[0],flag);CHKERRQ(ierr); 702443836d0SMatthew G Knepley ierr = VecDuplicate(jac->head->x, &jac->head->z);CHKERRQ(ierr); 703443836d0SMatthew G Knepley } else { 704443836d0SMatthew G Knepley jac->kspupper = jac->head->ksp; 705443836d0SMatthew G Knepley ierr = PetscObjectReference((PetscObject) jac->head->ksp);CHKERRQ(ierr); 706443836d0SMatthew G Knepley } 707443836d0SMatthew G Knepley 708a7476a74SDmitry Karpeev if (jac->schurpre == PC_FIELDSPLIT_SCHUR_PRE_SELFP) { 709*45e7fc46SDmitry Karpeev ierr = MatSchurComplementSetPmatLumping(jac->schur,jac->schurp_lump);CHKERRQ(ierr); 710a7476a74SDmitry Karpeev ierr = MatSchurComplementGetPmat(jac->schur,MAT_INITIAL_MATRIX,&jac->schurp);CHKERRQ(ierr); 711a7476a74SDmitry Karpeev } 712ce94432eSBarry Smith ierr = KSPCreate(PetscObjectComm((PetscObject)pc),&jac->kspschur);CHKERRQ(ierr); 71397bbdb24SBarry Smith ierr = PetscLogObjectParent((PetscObject)pc,(PetscObject)jac->kspschur);CHKERRQ(ierr); 71420252d06SBarry Smith ierr = PetscObjectIncrementTabLevel((PetscObject)jac->kspschur,(PetscObject)pc,1);CHKERRQ(ierr); 71597bbdb24SBarry Smith ierr = KSPSetOperators(jac->kspschur,jac->schur,FieldSplitSchurPre(jac),DIFFERENT_NONZERO_PATTERN);CHKERRQ(ierr); 71697bbdb24SBarry Smith if (jac->schurpre == PC_FIELDSPLIT_SCHUR_PRE_SELF) { 7177233a360SDmitry Karpeev PC pcschur; 7187233a360SDmitry Karpeev ierr = KSPGetPC(jac->kspschur,&pcschur);CHKERRQ(ierr); 7197233a360SDmitry Karpeev ierr = PCSetType(pcschur,PCNONE);CHKERRQ(ierr); 72097bbdb24SBarry Smith /* Note: This is bad if there exist preconditioners for MATSCHURCOMPLEMENT */ 72197bbdb24SBarry Smith } 72297bbdb24SBarry Smith ierr = KSPGetOptionsPrefix(jac->head->next->ksp, &Dprefix);CHKERRQ(ierr); 72397bbdb24SBarry Smith ierr = KSPSetOptionsPrefix(jac->kspschur, Dprefix);CHKERRQ(ierr); 724b20b4189SMatthew G. Knepley /* propogate DM */ 725b20b4189SMatthew G. Knepley { 726b20b4189SMatthew G. Knepley DM sdm; 727b20b4189SMatthew G. Knepley ierr = KSPGetDM(jac->head->next->ksp, &sdm);CHKERRQ(ierr); 728b20b4189SMatthew G. Knepley if (sdm) { 729b20b4189SMatthew G. Knepley ierr = KSPSetDM(jac->kspschur, sdm);CHKERRQ(ierr); 730b20b4189SMatthew G. Knepley ierr = KSPSetDMActive(jac->kspschur, PETSC_FALSE);CHKERRQ(ierr); 731b20b4189SMatthew G. Knepley } 732b20b4189SMatthew G. Knepley } 73397bbdb24SBarry Smith /* really want setfromoptions called in PCSetFromOptions_FieldSplit(), but it is not ready yet */ 73497bbdb24SBarry Smith /* need to call this every time, since the jac->kspschur is freshly created, otherwise its options never get set */ 73597bbdb24SBarry Smith ierr = KSPSetFromOptions(jac->kspschur);CHKERRQ(ierr); 73697bbdb24SBarry Smith } 73797bbdb24SBarry Smith 7385a9f2f41SSatish Balay /* HACK: special support to forward L and Lp matrices that might be used by PCLSC */ 7398caf3d72SBarry Smith ierr = PetscSNPrintf(lscname,sizeof(lscname),"%s_LSC_L",ilink->splitname);CHKERRQ(ierr); 740519d70e2SJed Brown ierr = PetscObjectQuery((PetscObject)pc->mat,lscname,(PetscObject*)&LSC_L);CHKERRQ(ierr); 7413b224e63SBarry Smith if (!LSC_L) {ierr = PetscObjectQuery((PetscObject)pc->pmat,lscname,(PetscObject*)&LSC_L);CHKERRQ(ierr);} 742c1570756SJed Brown if (LSC_L) {ierr = PetscObjectCompose((PetscObject)jac->schur,"LSC_L",(PetscObject)LSC_L);CHKERRQ(ierr);} 7438caf3d72SBarry Smith ierr = PetscSNPrintf(lscname,sizeof(lscname),"%s_LSC_Lp",ilink->splitname);CHKERRQ(ierr); 74497bbdb24SBarry Smith ierr = PetscObjectQuery((PetscObject)pc->pmat,lscname,(PetscObject*)&LSC_L);CHKERRQ(ierr); 7455a9f2f41SSatish Balay if (!LSC_L) {ierr = PetscObjectQuery((PetscObject)pc->mat,lscname,(PetscObject*)&LSC_L);CHKERRQ(ierr);} 7460971522cSBarry Smith if (LSC_L) {ierr = PetscObjectCompose((PetscObject)jac->schur,"LSC_Lp",(PetscObject)LSC_L);CHKERRQ(ierr);} 74797bbdb24SBarry Smith } else { 74868bd789dSDmitry Karpeev /* set up the individual splits' PCs */ 7490971522cSBarry Smith i = 0; 7500971522cSBarry Smith ilink = jac->head; 7510971522cSBarry Smith while (ilink) { 7520971522cSBarry Smith ierr = KSPSetOperators(ilink->ksp,jac->mat[i],jac->pmat[i],flag);CHKERRQ(ierr); 7530971522cSBarry Smith /* really want setfromoptions called in PCSetFromOptions_FieldSplit(), but it is not ready yet */ 7540971522cSBarry Smith if (!jac->suboptionsset) {ierr = KSPSetFromOptions(ilink->ksp);CHKERRQ(ierr);} 7550971522cSBarry Smith i++; 7560971522cSBarry Smith ilink = ilink->next; 7570971522cSBarry Smith } 7583b224e63SBarry Smith } 7593b224e63SBarry Smith 760c1570756SJed Brown jac->suboptionsset = PETSC_TRUE; 7610971522cSBarry Smith PetscFunctionReturn(0); 7620971522cSBarry Smith } 7630971522cSBarry Smith 7645a9f2f41SSatish Balay #define FieldSplitSplitSolveAdd(ilink,xx,yy) \ 765ca9f406cSSatish Balay (VecScatterBegin(ilink->sctx,xx,ilink->x,INSERT_VALUES,SCATTER_FORWARD) || \ 766ca9f406cSSatish Balay VecScatterEnd(ilink->sctx,xx,ilink->x,INSERT_VALUES,SCATTER_FORWARD) || \ 7675a9f2f41SSatish Balay KSPSolve(ilink->ksp,ilink->x,ilink->y) || \ 768ca9f406cSSatish Balay VecScatterBegin(ilink->sctx,ilink->y,yy,ADD_VALUES,SCATTER_REVERSE) || \ 769ca9f406cSSatish Balay VecScatterEnd(ilink->sctx,ilink->y,yy,ADD_VALUES,SCATTER_REVERSE)) 77079416396SBarry Smith 7710971522cSBarry Smith #undef __FUNCT__ 7723b224e63SBarry Smith #define __FUNCT__ "PCApply_FieldSplit_Schur" 7733b224e63SBarry Smith static PetscErrorCode PCApply_FieldSplit_Schur(PC pc,Vec x,Vec y) 7743b224e63SBarry Smith { 7753b224e63SBarry Smith PC_FieldSplit *jac = (PC_FieldSplit*)pc->data; 7763b224e63SBarry Smith PetscErrorCode ierr; 7773b224e63SBarry Smith PC_FieldSplitLink ilinkA = jac->head, ilinkD = ilinkA->next; 778443836d0SMatthew G Knepley KSP kspA = ilinkA->ksp, kspLower = kspA, kspUpper = jac->kspupper; 7793b224e63SBarry Smith 7803b224e63SBarry Smith PetscFunctionBegin; 781c5d2311dSJed Brown switch (jac->schurfactorization) { 782c9c6ffaaSJed Brown case PC_FIELDSPLIT_SCHUR_FACT_DIAG: 783a04f6461SBarry Smith /* [A00 0; 0 -S], positive definite, suitable for MINRES */ 784c5d2311dSJed Brown ierr = VecScatterBegin(ilinkA->sctx,x,ilinkA->x,INSERT_VALUES,SCATTER_FORWARD);CHKERRQ(ierr); 785c5d2311dSJed Brown ierr = VecScatterBegin(ilinkD->sctx,x,ilinkD->x,INSERT_VALUES,SCATTER_FORWARD);CHKERRQ(ierr); 786c5d2311dSJed Brown ierr = VecScatterEnd(ilinkA->sctx,x,ilinkA->x,INSERT_VALUES,SCATTER_FORWARD);CHKERRQ(ierr); 787443836d0SMatthew G Knepley ierr = KSPSolve(kspA,ilinkA->x,ilinkA->y);CHKERRQ(ierr); 788c5d2311dSJed Brown ierr = VecScatterBegin(ilinkA->sctx,ilinkA->y,y,INSERT_VALUES,SCATTER_REVERSE);CHKERRQ(ierr); 789c5d2311dSJed Brown ierr = VecScatterEnd(ilinkD->sctx,x,ilinkD->x,INSERT_VALUES,SCATTER_FORWARD);CHKERRQ(ierr); 790c5d2311dSJed Brown ierr = KSPSolve(jac->kspschur,ilinkD->x,ilinkD->y);CHKERRQ(ierr); 791c5d2311dSJed Brown ierr = VecScale(ilinkD->y,-1.);CHKERRQ(ierr); 792c5d2311dSJed Brown ierr = VecScatterBegin(ilinkD->sctx,ilinkD->y,y,INSERT_VALUES,SCATTER_REVERSE);CHKERRQ(ierr); 793c5d2311dSJed Brown ierr = VecScatterEnd(ilinkA->sctx,ilinkA->y,y,INSERT_VALUES,SCATTER_REVERSE);CHKERRQ(ierr); 794c5d2311dSJed Brown ierr = VecScatterEnd(ilinkD->sctx,ilinkD->y,y,INSERT_VALUES,SCATTER_REVERSE);CHKERRQ(ierr); 795c5d2311dSJed Brown break; 796c9c6ffaaSJed Brown case PC_FIELDSPLIT_SCHUR_FACT_LOWER: 797a04f6461SBarry Smith /* [A00 0; A10 S], suitable for left preconditioning */ 798c5d2311dSJed Brown ierr = VecScatterBegin(ilinkA->sctx,x,ilinkA->x,INSERT_VALUES,SCATTER_FORWARD);CHKERRQ(ierr); 799c5d2311dSJed Brown ierr = VecScatterEnd(ilinkA->sctx,x,ilinkA->x,INSERT_VALUES,SCATTER_FORWARD);CHKERRQ(ierr); 800443836d0SMatthew G Knepley ierr = KSPSolve(kspA,ilinkA->x,ilinkA->y);CHKERRQ(ierr); 801c5d2311dSJed Brown ierr = MatMult(jac->C,ilinkA->y,ilinkD->x);CHKERRQ(ierr); 802c5d2311dSJed Brown ierr = VecScale(ilinkD->x,-1.);CHKERRQ(ierr); 803c5d2311dSJed Brown ierr = VecScatterBegin(ilinkD->sctx,x,ilinkD->x,ADD_VALUES,SCATTER_FORWARD);CHKERRQ(ierr); 804c5d2311dSJed Brown ierr = VecScatterBegin(ilinkA->sctx,ilinkA->y,y,INSERT_VALUES,SCATTER_REVERSE);CHKERRQ(ierr); 805c5d2311dSJed Brown ierr = VecScatterEnd(ilinkD->sctx,x,ilinkD->x,ADD_VALUES,SCATTER_FORWARD);CHKERRQ(ierr); 806c5d2311dSJed Brown ierr = KSPSolve(jac->kspschur,ilinkD->x,ilinkD->y);CHKERRQ(ierr); 807c5d2311dSJed Brown ierr = VecScatterBegin(ilinkD->sctx,ilinkD->y,y,INSERT_VALUES,SCATTER_REVERSE);CHKERRQ(ierr); 808c5d2311dSJed Brown ierr = VecScatterEnd(ilinkA->sctx,ilinkA->y,y,INSERT_VALUES,SCATTER_REVERSE);CHKERRQ(ierr); 809c5d2311dSJed Brown ierr = VecScatterEnd(ilinkD->sctx,ilinkD->y,y,INSERT_VALUES,SCATTER_REVERSE);CHKERRQ(ierr); 810c5d2311dSJed Brown break; 811c9c6ffaaSJed Brown case PC_FIELDSPLIT_SCHUR_FACT_UPPER: 812a04f6461SBarry Smith /* [A00 A01; 0 S], suitable for right preconditioning */ 813c5d2311dSJed Brown ierr = VecScatterBegin(ilinkD->sctx,x,ilinkD->x,INSERT_VALUES,SCATTER_FORWARD);CHKERRQ(ierr); 814c5d2311dSJed Brown ierr = VecScatterEnd(ilinkD->sctx,x,ilinkD->x,INSERT_VALUES,SCATTER_FORWARD);CHKERRQ(ierr); 815c5d2311dSJed Brown ierr = KSPSolve(jac->kspschur,ilinkD->x,ilinkD->y);CHKERRQ(ierr); 816c5d2311dSJed Brown ierr = MatMult(jac->B,ilinkD->y,ilinkA->x);CHKERRQ(ierr); 817c5d2311dSJed Brown ierr = VecScale(ilinkA->x,-1.);CHKERRQ(ierr); 818c5d2311dSJed Brown ierr = VecScatterBegin(ilinkA->sctx,x,ilinkA->x,ADD_VALUES,SCATTER_FORWARD);CHKERRQ(ierr); 819c5d2311dSJed Brown ierr = VecScatterBegin(ilinkD->sctx,ilinkD->y,y,INSERT_VALUES,SCATTER_REVERSE);CHKERRQ(ierr); 820c5d2311dSJed Brown ierr = VecScatterEnd(ilinkA->sctx,x,ilinkA->x,ADD_VALUES,SCATTER_FORWARD);CHKERRQ(ierr); 821443836d0SMatthew G Knepley ierr = KSPSolve(kspA,ilinkA->x,ilinkA->y);CHKERRQ(ierr); 822c5d2311dSJed Brown ierr = VecScatterBegin(ilinkA->sctx,ilinkA->y,y,INSERT_VALUES,SCATTER_REVERSE);CHKERRQ(ierr); 823c5d2311dSJed Brown ierr = VecScatterEnd(ilinkD->sctx,ilinkD->y,y,INSERT_VALUES,SCATTER_REVERSE);CHKERRQ(ierr); 824c5d2311dSJed Brown ierr = VecScatterEnd(ilinkA->sctx,ilinkA->y,y,INSERT_VALUES,SCATTER_REVERSE);CHKERRQ(ierr); 825c5d2311dSJed Brown break; 826c9c6ffaaSJed Brown case PC_FIELDSPLIT_SCHUR_FACT_FULL: 827a04f6461SBarry Smith /* [1 0; A10 A00^{-1} 1] [A00 0; 0 S] [1 A00^{-1}A01; 0 1], an exact solve if applied exactly, needs one extra solve with A */ 8283b224e63SBarry Smith ierr = VecScatterBegin(ilinkA->sctx,x,ilinkA->x,INSERT_VALUES,SCATTER_FORWARD);CHKERRQ(ierr); 8293b224e63SBarry Smith ierr = VecScatterEnd(ilinkA->sctx,x,ilinkA->x,INSERT_VALUES,SCATTER_FORWARD);CHKERRQ(ierr); 830443836d0SMatthew G Knepley ierr = KSPSolve(kspLower,ilinkA->x,ilinkA->y);CHKERRQ(ierr); 8313b224e63SBarry Smith ierr = MatMult(jac->C,ilinkA->y,ilinkD->x);CHKERRQ(ierr); 8323b224e63SBarry Smith ierr = VecScale(ilinkD->x,-1.0);CHKERRQ(ierr); 8333b224e63SBarry Smith ierr = VecScatterBegin(ilinkD->sctx,x,ilinkD->x,ADD_VALUES,SCATTER_FORWARD);CHKERRQ(ierr); 8343b224e63SBarry Smith ierr = VecScatterEnd(ilinkD->sctx,x,ilinkD->x,ADD_VALUES,SCATTER_FORWARD);CHKERRQ(ierr); 8353b224e63SBarry Smith 8363b224e63SBarry Smith ierr = KSPSolve(jac->kspschur,ilinkD->x,ilinkD->y);CHKERRQ(ierr); 8373b224e63SBarry Smith ierr = VecScatterBegin(ilinkD->sctx,ilinkD->y,y,INSERT_VALUES,SCATTER_REVERSE);CHKERRQ(ierr); 8383b224e63SBarry Smith ierr = VecScatterEnd(ilinkD->sctx,ilinkD->y,y,INSERT_VALUES,SCATTER_REVERSE);CHKERRQ(ierr); 8393b224e63SBarry Smith 840443836d0SMatthew G Knepley if (kspUpper == kspA) { 8413b224e63SBarry Smith ierr = MatMult(jac->B,ilinkD->y,ilinkA->y);CHKERRQ(ierr); 8423b224e63SBarry Smith ierr = VecAXPY(ilinkA->x,-1.0,ilinkA->y);CHKERRQ(ierr); 843443836d0SMatthew G Knepley ierr = KSPSolve(kspA,ilinkA->x,ilinkA->y);CHKERRQ(ierr); 844443836d0SMatthew G Knepley } else { 845443836d0SMatthew G Knepley ierr = KSPSolve(kspA,ilinkA->x,ilinkA->y);CHKERRQ(ierr); 846443836d0SMatthew G Knepley ierr = MatMult(jac->B,ilinkD->y,ilinkA->x);CHKERRQ(ierr); 847443836d0SMatthew G Knepley ierr = KSPSolve(kspUpper,ilinkA->x,ilinkA->z);CHKERRQ(ierr); 848443836d0SMatthew G Knepley ierr = VecAXPY(ilinkA->y,-1.0,ilinkA->z);CHKERRQ(ierr); 849443836d0SMatthew G Knepley } 8503b224e63SBarry Smith ierr = VecScatterBegin(ilinkA->sctx,ilinkA->y,y,INSERT_VALUES,SCATTER_REVERSE);CHKERRQ(ierr); 8513b224e63SBarry Smith ierr = VecScatterEnd(ilinkA->sctx,ilinkA->y,y,INSERT_VALUES,SCATTER_REVERSE);CHKERRQ(ierr); 852c5d2311dSJed Brown } 8533b224e63SBarry Smith PetscFunctionReturn(0); 8543b224e63SBarry Smith } 8553b224e63SBarry Smith 8563b224e63SBarry Smith #undef __FUNCT__ 8570971522cSBarry Smith #define __FUNCT__ "PCApply_FieldSplit" 8580971522cSBarry Smith static PetscErrorCode PCApply_FieldSplit(PC pc,Vec x,Vec y) 8590971522cSBarry Smith { 8600971522cSBarry Smith PC_FieldSplit *jac = (PC_FieldSplit*)pc->data; 8610971522cSBarry Smith PetscErrorCode ierr; 8625a9f2f41SSatish Balay PC_FieldSplitLink ilink = jac->head; 863939b8a20SBarry Smith PetscInt cnt,bs; 8640971522cSBarry Smith 8650971522cSBarry Smith PetscFunctionBegin; 86679416396SBarry Smith if (jac->type == PC_COMPOSITE_ADDITIVE) { 8671b9fc7fcSBarry Smith if (jac->defaultsplit) { 868939b8a20SBarry Smith ierr = VecGetBlockSize(x,&bs);CHKERRQ(ierr); 869ce94432eSBarry Smith if (jac->bs > 0 && bs != jac->bs) SETERRQ2(PetscObjectComm((PetscObject)pc),PETSC_ERR_ARG_WRONGSTATE,"Blocksize of x vector %D does not match fieldsplit blocksize %D",bs,jac->bs); 870939b8a20SBarry Smith ierr = VecGetBlockSize(y,&bs);CHKERRQ(ierr); 871ce94432eSBarry Smith if (jac->bs > 0 && bs != jac->bs) SETERRQ2(PetscObjectComm((PetscObject)pc),PETSC_ERR_ARG_WRONGSTATE,"Blocksize of y vector %D does not match fieldsplit blocksize %D",bs,jac->bs); 8720971522cSBarry Smith ierr = VecStrideGatherAll(x,jac->x,INSERT_VALUES);CHKERRQ(ierr); 8735a9f2f41SSatish Balay while (ilink) { 8745a9f2f41SSatish Balay ierr = KSPSolve(ilink->ksp,ilink->x,ilink->y);CHKERRQ(ierr); 8755a9f2f41SSatish Balay ilink = ilink->next; 8760971522cSBarry Smith } 8770971522cSBarry Smith ierr = VecStrideScatterAll(jac->y,y,INSERT_VALUES);CHKERRQ(ierr); 8781b9fc7fcSBarry Smith } else { 879efb30889SBarry Smith ierr = VecSet(y,0.0);CHKERRQ(ierr); 8805a9f2f41SSatish Balay while (ilink) { 8815a9f2f41SSatish Balay ierr = FieldSplitSplitSolveAdd(ilink,x,y);CHKERRQ(ierr); 8825a9f2f41SSatish Balay ilink = ilink->next; 8831b9fc7fcSBarry Smith } 8841b9fc7fcSBarry Smith } 88516913363SBarry Smith } else if (jac->type == PC_COMPOSITE_MULTIPLICATIVE || jac->type == PC_COMPOSITE_SYMMETRIC_MULTIPLICATIVE) { 88679416396SBarry Smith if (!jac->w1) { 88779416396SBarry Smith ierr = VecDuplicate(x,&jac->w1);CHKERRQ(ierr); 88879416396SBarry Smith ierr = VecDuplicate(x,&jac->w2);CHKERRQ(ierr); 88979416396SBarry Smith } 890efb30889SBarry Smith ierr = VecSet(y,0.0);CHKERRQ(ierr); 8915a9f2f41SSatish Balay ierr = FieldSplitSplitSolveAdd(ilink,x,y);CHKERRQ(ierr); 8923e197d65SBarry Smith cnt = 1; 8935a9f2f41SSatish Balay while (ilink->next) { 8945a9f2f41SSatish Balay ilink = ilink->next; 8953e197d65SBarry Smith /* compute the residual only over the part of the vector needed */ 8963e197d65SBarry Smith ierr = MatMult(jac->Afield[cnt++],y,ilink->x);CHKERRQ(ierr); 8973e197d65SBarry Smith ierr = VecScale(ilink->x,-1.0);CHKERRQ(ierr); 8983e197d65SBarry Smith ierr = VecScatterBegin(ilink->sctx,x,ilink->x,ADD_VALUES,SCATTER_FORWARD);CHKERRQ(ierr); 8993e197d65SBarry Smith ierr = VecScatterEnd(ilink->sctx,x,ilink->x,ADD_VALUES,SCATTER_FORWARD);CHKERRQ(ierr); 9003e197d65SBarry Smith ierr = KSPSolve(ilink->ksp,ilink->x,ilink->y);CHKERRQ(ierr); 9013e197d65SBarry Smith ierr = VecScatterBegin(ilink->sctx,ilink->y,y,ADD_VALUES,SCATTER_REVERSE);CHKERRQ(ierr); 9023e197d65SBarry Smith ierr = VecScatterEnd(ilink->sctx,ilink->y,y,ADD_VALUES,SCATTER_REVERSE);CHKERRQ(ierr); 9033e197d65SBarry Smith } 90451f519a2SBarry Smith if (jac->type == PC_COMPOSITE_SYMMETRIC_MULTIPLICATIVE) { 90511755939SBarry Smith cnt -= 2; 90651f519a2SBarry Smith while (ilink->previous) { 90751f519a2SBarry Smith ilink = ilink->previous; 90811755939SBarry Smith /* compute the residual only over the part of the vector needed */ 90911755939SBarry Smith ierr = MatMult(jac->Afield[cnt--],y,ilink->x);CHKERRQ(ierr); 91011755939SBarry Smith ierr = VecScale(ilink->x,-1.0);CHKERRQ(ierr); 91111755939SBarry Smith ierr = VecScatterBegin(ilink->sctx,x,ilink->x,ADD_VALUES,SCATTER_FORWARD);CHKERRQ(ierr); 91211755939SBarry Smith ierr = VecScatterEnd(ilink->sctx,x,ilink->x,ADD_VALUES,SCATTER_FORWARD);CHKERRQ(ierr); 91311755939SBarry Smith ierr = KSPSolve(ilink->ksp,ilink->x,ilink->y);CHKERRQ(ierr); 91411755939SBarry Smith ierr = VecScatterBegin(ilink->sctx,ilink->y,y,ADD_VALUES,SCATTER_REVERSE);CHKERRQ(ierr); 91511755939SBarry Smith ierr = VecScatterEnd(ilink->sctx,ilink->y,y,ADD_VALUES,SCATTER_REVERSE);CHKERRQ(ierr); 91651f519a2SBarry Smith } 91711755939SBarry Smith } 918ce94432eSBarry Smith } else SETERRQ1(PetscObjectComm((PetscObject)pc),PETSC_ERR_SUP,"Unsupported or unknown composition",(int) jac->type); 9190971522cSBarry Smith PetscFunctionReturn(0); 9200971522cSBarry Smith } 9210971522cSBarry Smith 922421e10b8SBarry Smith #define FieldSplitSplitSolveAddTranspose(ilink,xx,yy) \ 923ca9f406cSSatish Balay (VecScatterBegin(ilink->sctx,xx,ilink->y,INSERT_VALUES,SCATTER_FORWARD) || \ 924ca9f406cSSatish Balay VecScatterEnd(ilink->sctx,xx,ilink->y,INSERT_VALUES,SCATTER_FORWARD) || \ 925421e10b8SBarry Smith KSPSolveTranspose(ilink->ksp,ilink->y,ilink->x) || \ 926ca9f406cSSatish Balay VecScatterBegin(ilink->sctx,ilink->x,yy,ADD_VALUES,SCATTER_REVERSE) || \ 927ca9f406cSSatish Balay VecScatterEnd(ilink->sctx,ilink->x,yy,ADD_VALUES,SCATTER_REVERSE)) 928421e10b8SBarry Smith 929421e10b8SBarry Smith #undef __FUNCT__ 9308c03b21aSDmitry Karpeev #define __FUNCT__ "PCApplyTranspose_FieldSplit" 931421e10b8SBarry Smith static PetscErrorCode PCApplyTranspose_FieldSplit(PC pc,Vec x,Vec y) 932421e10b8SBarry Smith { 933421e10b8SBarry Smith PC_FieldSplit *jac = (PC_FieldSplit*)pc->data; 934421e10b8SBarry Smith PetscErrorCode ierr; 935421e10b8SBarry Smith PC_FieldSplitLink ilink = jac->head; 936939b8a20SBarry Smith PetscInt bs; 937421e10b8SBarry Smith 938421e10b8SBarry Smith PetscFunctionBegin; 939421e10b8SBarry Smith if (jac->type == PC_COMPOSITE_ADDITIVE) { 940421e10b8SBarry Smith if (jac->defaultsplit) { 941939b8a20SBarry Smith ierr = VecGetBlockSize(x,&bs);CHKERRQ(ierr); 942ce94432eSBarry Smith if (jac->bs > 0 && bs != jac->bs) SETERRQ2(PetscObjectComm((PetscObject)pc),PETSC_ERR_ARG_WRONGSTATE,"Blocksize of x vector %D does not match fieldsplit blocksize %D",bs,jac->bs); 943939b8a20SBarry Smith ierr = VecGetBlockSize(y,&bs);CHKERRQ(ierr); 944ce94432eSBarry Smith if (jac->bs > 0 && bs != jac->bs) SETERRQ2(PetscObjectComm((PetscObject)pc),PETSC_ERR_ARG_WRONGSTATE,"Blocksize of y vector %D does not match fieldsplit blocksize %D",bs,jac->bs); 945421e10b8SBarry Smith ierr = VecStrideGatherAll(x,jac->x,INSERT_VALUES);CHKERRQ(ierr); 946421e10b8SBarry Smith while (ilink) { 947421e10b8SBarry Smith ierr = KSPSolveTranspose(ilink->ksp,ilink->x,ilink->y);CHKERRQ(ierr); 948421e10b8SBarry Smith ilink = ilink->next; 949421e10b8SBarry Smith } 950421e10b8SBarry Smith ierr = VecStrideScatterAll(jac->y,y,INSERT_VALUES);CHKERRQ(ierr); 951421e10b8SBarry Smith } else { 952421e10b8SBarry Smith ierr = VecSet(y,0.0);CHKERRQ(ierr); 953421e10b8SBarry Smith while (ilink) { 954421e10b8SBarry Smith ierr = FieldSplitSplitSolveAddTranspose(ilink,x,y);CHKERRQ(ierr); 955421e10b8SBarry Smith ilink = ilink->next; 956421e10b8SBarry Smith } 957421e10b8SBarry Smith } 958421e10b8SBarry Smith } else { 959421e10b8SBarry Smith if (!jac->w1) { 960421e10b8SBarry Smith ierr = VecDuplicate(x,&jac->w1);CHKERRQ(ierr); 961421e10b8SBarry Smith ierr = VecDuplicate(x,&jac->w2);CHKERRQ(ierr); 962421e10b8SBarry Smith } 963421e10b8SBarry Smith ierr = VecSet(y,0.0);CHKERRQ(ierr); 964421e10b8SBarry Smith if (jac->type == PC_COMPOSITE_SYMMETRIC_MULTIPLICATIVE) { 965421e10b8SBarry Smith ierr = FieldSplitSplitSolveAddTranspose(ilink,x,y);CHKERRQ(ierr); 966421e10b8SBarry Smith while (ilink->next) { 967421e10b8SBarry Smith ilink = ilink->next; 9689989ab13SBarry Smith ierr = MatMultTranspose(pc->mat,y,jac->w1);CHKERRQ(ierr); 969421e10b8SBarry Smith ierr = VecWAXPY(jac->w2,-1.0,jac->w1,x);CHKERRQ(ierr); 970421e10b8SBarry Smith ierr = FieldSplitSplitSolveAddTranspose(ilink,jac->w2,y);CHKERRQ(ierr); 971421e10b8SBarry Smith } 972421e10b8SBarry Smith while (ilink->previous) { 973421e10b8SBarry Smith ilink = ilink->previous; 9749989ab13SBarry Smith ierr = MatMultTranspose(pc->mat,y,jac->w1);CHKERRQ(ierr); 975421e10b8SBarry Smith ierr = VecWAXPY(jac->w2,-1.0,jac->w1,x);CHKERRQ(ierr); 976421e10b8SBarry Smith ierr = FieldSplitSplitSolveAddTranspose(ilink,jac->w2,y);CHKERRQ(ierr); 977421e10b8SBarry Smith } 978421e10b8SBarry Smith } else { 979421e10b8SBarry Smith while (ilink->next) { /* get to last entry in linked list */ 980421e10b8SBarry Smith ilink = ilink->next; 981421e10b8SBarry Smith } 982421e10b8SBarry Smith ierr = FieldSplitSplitSolveAddTranspose(ilink,x,y);CHKERRQ(ierr); 983421e10b8SBarry Smith while (ilink->previous) { 984421e10b8SBarry Smith ilink = ilink->previous; 9859989ab13SBarry Smith ierr = MatMultTranspose(pc->mat,y,jac->w1);CHKERRQ(ierr); 986421e10b8SBarry Smith ierr = VecWAXPY(jac->w2,-1.0,jac->w1,x);CHKERRQ(ierr); 987421e10b8SBarry Smith ierr = FieldSplitSplitSolveAddTranspose(ilink,jac->w2,y);CHKERRQ(ierr); 988421e10b8SBarry Smith } 989421e10b8SBarry Smith } 990421e10b8SBarry Smith } 991421e10b8SBarry Smith PetscFunctionReturn(0); 992421e10b8SBarry Smith } 993421e10b8SBarry Smith 9940971522cSBarry Smith #undef __FUNCT__ 995574deadeSBarry Smith #define __FUNCT__ "PCReset_FieldSplit" 996574deadeSBarry Smith static PetscErrorCode PCReset_FieldSplit(PC pc) 9970971522cSBarry Smith { 9980971522cSBarry Smith PC_FieldSplit *jac = (PC_FieldSplit*)pc->data; 9990971522cSBarry Smith PetscErrorCode ierr; 10005a9f2f41SSatish Balay PC_FieldSplitLink ilink = jac->head,next; 10010971522cSBarry Smith 10020971522cSBarry Smith PetscFunctionBegin; 10035a9f2f41SSatish Balay while (ilink) { 1004574deadeSBarry Smith ierr = KSPReset(ilink->ksp);CHKERRQ(ierr); 1005fcfd50ebSBarry Smith ierr = VecDestroy(&ilink->x);CHKERRQ(ierr); 1006fcfd50ebSBarry Smith ierr = VecDestroy(&ilink->y);CHKERRQ(ierr); 1007443836d0SMatthew G Knepley ierr = VecDestroy(&ilink->z);CHKERRQ(ierr); 1008fcfd50ebSBarry Smith ierr = VecScatterDestroy(&ilink->sctx);CHKERRQ(ierr); 1009fcfd50ebSBarry Smith ierr = ISDestroy(&ilink->is);CHKERRQ(ierr); 1010b5787286SJed Brown ierr = ISDestroy(&ilink->is_col);CHKERRQ(ierr); 10115a9f2f41SSatish Balay next = ilink->next; 10125a9f2f41SSatish Balay ilink = next; 10130971522cSBarry Smith } 101405b42c5fSBarry Smith ierr = PetscFree2(jac->x,jac->y);CHKERRQ(ierr); 1015574deadeSBarry Smith if (jac->mat && jac->mat != jac->pmat) { 1016574deadeSBarry Smith ierr = MatDestroyMatrices(jac->nsplits,&jac->mat);CHKERRQ(ierr); 1017574deadeSBarry Smith } else if (jac->mat) { 10180298fd71SBarry Smith jac->mat = NULL; 1019574deadeSBarry Smith } 102097bbdb24SBarry Smith if (jac->pmat) {ierr = MatDestroyMatrices(jac->nsplits,&jac->pmat);CHKERRQ(ierr);} 102168dd23aaSBarry Smith if (jac->Afield) {ierr = MatDestroyMatrices(jac->nsplits,&jac->Afield);CHKERRQ(ierr);} 10226bf464f9SBarry Smith ierr = VecDestroy(&jac->w1);CHKERRQ(ierr); 10236bf464f9SBarry Smith ierr = VecDestroy(&jac->w2);CHKERRQ(ierr); 10246bf464f9SBarry Smith ierr = MatDestroy(&jac->schur);CHKERRQ(ierr); 1025a7476a74SDmitry Karpeev ierr = MatDestroy(&jac->schurp);CHKERRQ(ierr); 10266bf464f9SBarry Smith ierr = MatDestroy(&jac->schur_user);CHKERRQ(ierr); 10276bf464f9SBarry Smith ierr = KSPDestroy(&jac->kspschur);CHKERRQ(ierr); 1028d78dad28SBarry Smith ierr = KSPDestroy(&jac->kspupper);CHKERRQ(ierr); 10296bf464f9SBarry Smith ierr = MatDestroy(&jac->B);CHKERRQ(ierr); 10306bf464f9SBarry Smith ierr = MatDestroy(&jac->C);CHKERRQ(ierr); 103163ec74ffSBarry Smith jac->reset = PETSC_TRUE; 1032574deadeSBarry Smith PetscFunctionReturn(0); 1033574deadeSBarry Smith } 1034574deadeSBarry Smith 1035574deadeSBarry Smith #undef __FUNCT__ 1036574deadeSBarry Smith #define __FUNCT__ "PCDestroy_FieldSplit" 1037574deadeSBarry Smith static PetscErrorCode PCDestroy_FieldSplit(PC pc) 1038574deadeSBarry Smith { 1039574deadeSBarry Smith PC_FieldSplit *jac = (PC_FieldSplit*)pc->data; 1040574deadeSBarry Smith PetscErrorCode ierr; 1041574deadeSBarry Smith PC_FieldSplitLink ilink = jac->head,next; 1042574deadeSBarry Smith 1043574deadeSBarry Smith PetscFunctionBegin; 1044574deadeSBarry Smith ierr = PCReset_FieldSplit(pc);CHKERRQ(ierr); 1045574deadeSBarry Smith while (ilink) { 10466bf464f9SBarry Smith ierr = KSPDestroy(&ilink->ksp);CHKERRQ(ierr); 1047574deadeSBarry Smith next = ilink->next; 1048574deadeSBarry Smith ierr = PetscFree(ilink->splitname);CHKERRQ(ierr); 1049574deadeSBarry Smith ierr = PetscFree(ilink->fields);CHKERRQ(ierr); 10505d4c12cdSJungho Lee ierr = PetscFree(ilink->fields_col);CHKERRQ(ierr); 1051574deadeSBarry Smith ierr = PetscFree(ilink);CHKERRQ(ierr); 1052574deadeSBarry Smith ilink = next; 1053574deadeSBarry Smith } 1054574deadeSBarry Smith ierr = PetscFree2(jac->x,jac->y);CHKERRQ(ierr); 1055c31cb41cSBarry Smith ierr = PetscFree(pc->data);CHKERRQ(ierr); 1056bdf89e91SBarry Smith ierr = PetscObjectComposeFunction((PetscObject)pc,"PCFieldSplitGetSubKSP_C",NULL);CHKERRQ(ierr); 1057bdf89e91SBarry Smith ierr = PetscObjectComposeFunction((PetscObject)pc,"PCFieldSplitSetFields_C",NULL);CHKERRQ(ierr); 1058bdf89e91SBarry Smith ierr = PetscObjectComposeFunction((PetscObject)pc,"PCFieldSplitSetIS_C",NULL);CHKERRQ(ierr); 1059bdf89e91SBarry Smith ierr = PetscObjectComposeFunction((PetscObject)pc,"PCFieldSplitSetType_C",NULL);CHKERRQ(ierr); 1060bdf89e91SBarry Smith ierr = PetscObjectComposeFunction((PetscObject)pc,"PCFieldSplitSetBlockSize_C",NULL);CHKERRQ(ierr); 1061bdf89e91SBarry Smith ierr = PetscObjectComposeFunction((PetscObject)pc,"PCFieldSplitSchurPrecondition_C",NULL);CHKERRQ(ierr); 1062bdf89e91SBarry Smith ierr = PetscObjectComposeFunction((PetscObject)pc,"PCFieldSplitSetSchurFactType_C",NULL);CHKERRQ(ierr); 10630971522cSBarry Smith PetscFunctionReturn(0); 10640971522cSBarry Smith } 10650971522cSBarry Smith 10660971522cSBarry Smith #undef __FUNCT__ 10670971522cSBarry Smith #define __FUNCT__ "PCSetFromOptions_FieldSplit" 10680971522cSBarry Smith static PetscErrorCode PCSetFromOptions_FieldSplit(PC pc) 10690971522cSBarry Smith { 10701b9fc7fcSBarry Smith PetscErrorCode ierr; 10716c924f48SJed Brown PetscInt bs; 1072bc59fbc5SBarry Smith PetscBool flg,stokes = PETSC_FALSE; 10739dcbbd2bSBarry Smith PC_FieldSplit *jac = (PC_FieldSplit*)pc->data; 10743b224e63SBarry Smith PCCompositeType ctype; 10751b9fc7fcSBarry Smith 10760971522cSBarry Smith PetscFunctionBegin; 10771b9fc7fcSBarry Smith ierr = PetscOptionsHead("FieldSplit options");CHKERRQ(ierr); 10784ab8060aSDmitry Karpeev ierr = PetscOptionsBool("-pc_fieldsplit_dm_splits","Whether to use DMCreateFieldDecomposition() for splits","PCFieldSplitSetDMSplits",jac->dm_splits,&jac->dm_splits,NULL);CHKERRQ(ierr); 107951f519a2SBarry Smith ierr = PetscOptionsInt("-pc_fieldsplit_block_size","Blocksize that defines number of fields","PCFieldSplitSetBlockSize",jac->bs,&bs,&flg);CHKERRQ(ierr); 108051f519a2SBarry Smith if (flg) { 108151f519a2SBarry Smith ierr = PCFieldSplitSetBlockSize(pc,bs);CHKERRQ(ierr); 108251f519a2SBarry Smith } 1083704ba839SBarry Smith 10840298fd71SBarry Smith ierr = PetscOptionsGetBool(((PetscObject)pc)->prefix,"-pc_fieldsplit_detect_saddle_point",&stokes,NULL);CHKERRQ(ierr); 1085c0adfefeSBarry Smith if (stokes) { 1086c0adfefeSBarry Smith ierr = PCFieldSplitSetType(pc,PC_COMPOSITE_SCHUR);CHKERRQ(ierr); 1087c0adfefeSBarry Smith jac->schurpre = PC_FIELDSPLIT_SCHUR_PRE_SELF; 1088c0adfefeSBarry Smith } 1089c0adfefeSBarry Smith 10903b224e63SBarry Smith ierr = PetscOptionsEnum("-pc_fieldsplit_type","Type of composition","PCFieldSplitSetType",PCCompositeTypes,(PetscEnum)jac->type,(PetscEnum*)&ctype,&flg);CHKERRQ(ierr); 10913b224e63SBarry Smith if (flg) { 10923b224e63SBarry Smith ierr = PCFieldSplitSetType(pc,ctype);CHKERRQ(ierr); 10933b224e63SBarry Smith } 1094c30613efSMatthew Knepley /* Only setup fields once */ 1095c30613efSMatthew Knepley if ((jac->bs > 0) && (jac->nsplits == 0)) { 1096d32f9abdSBarry Smith /* only allow user to set fields from command line if bs is already known. 1097d32f9abdSBarry Smith otherwise user can set them in PCFieldSplitSetDefaults() */ 10986c924f48SJed Brown ierr = PCFieldSplitSetRuntimeSplits_Private(pc);CHKERRQ(ierr); 10996c924f48SJed Brown if (jac->splitdefined) {ierr = PetscInfo(pc,"Splits defined using the options database\n");CHKERRQ(ierr);} 1100d32f9abdSBarry Smith } 1101c5d2311dSJed Brown if (jac->type == PC_COMPOSITE_SCHUR) { 1102c9c6ffaaSJed Brown ierr = PetscOptionsGetEnum(((PetscObject)pc)->prefix,"-pc_fieldsplit_schur_factorization_type",PCFieldSplitSchurFactTypes,(PetscEnum*)&jac->schurfactorization,&flg);CHKERRQ(ierr); 1103c9c6ffaaSJed Brown if (flg) {ierr = PetscInfo(pc,"Deprecated use of -pc_fieldsplit_schur_factorization_type\n");CHKERRQ(ierr);} 11040298fd71SBarry 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); 11050298fd71SBarry Smith ierr = PetscOptionsEnum("-pc_fieldsplit_schur_precondition","How to build preconditioner for Schur complement","PCFieldSplitSchurPrecondition",PCFieldSplitSchurPreTypes,(PetscEnum)jac->schurpre,(PetscEnum*)&jac->schurpre,NULL);CHKERRQ(ierr); 1106*45e7fc46SDmitry Karpeev jac->schurp_lump = PETSC_FALSE; 1107*45e7fc46SDmitry Karpeev ierr = PetscOptionsBool("-pc_fieldsplit_schur_precondition_selfp_lump","Lump A00 when assembling selfp preconditioning matrix for Schur complement","PCFieldSplitSetSelfpLumping",jac->schurp_lump,&jac->schurp_lump,NULL);CHKERRQ(ierr); 1108c5d2311dSJed Brown } 11091b9fc7fcSBarry Smith ierr = PetscOptionsTail();CHKERRQ(ierr); 11100971522cSBarry Smith PetscFunctionReturn(0); 11110971522cSBarry Smith } 11120971522cSBarry Smith 11130971522cSBarry Smith /*------------------------------------------------------------------------------------*/ 11140971522cSBarry Smith 11150971522cSBarry Smith #undef __FUNCT__ 11160971522cSBarry Smith #define __FUNCT__ "PCFieldSplitSetFields_FieldSplit" 11171e6b0712SBarry Smith static PetscErrorCode PCFieldSplitSetFields_FieldSplit(PC pc,const char splitname[],PetscInt n,const PetscInt *fields,const PetscInt *fields_col) 11180971522cSBarry Smith { 111997bbdb24SBarry Smith PC_FieldSplit *jac = (PC_FieldSplit*)pc->data; 11200971522cSBarry Smith PetscErrorCode ierr; 11215a9f2f41SSatish Balay PC_FieldSplitLink ilink,next = jac->head; 112269a612a9SBarry Smith char prefix[128]; 11235d4c12cdSJungho Lee PetscInt i; 11240971522cSBarry Smith 11250971522cSBarry Smith PetscFunctionBegin; 11266c924f48SJed Brown if (jac->splitdefined) { 11276c924f48SJed Brown ierr = PetscInfo1(pc,"Ignoring new split \"%s\" because the splits have already been defined\n",splitname);CHKERRQ(ierr); 11286c924f48SJed Brown PetscFunctionReturn(0); 11296c924f48SJed Brown } 113051f519a2SBarry Smith for (i=0; i<n; i++) { 1131e32f2f54SBarry Smith if (fields[i] >= jac->bs) SETERRQ2(PETSC_COMM_SELF,PETSC_ERR_ARG_OUTOFRANGE,"Field %D requested but only %D exist",fields[i],jac->bs); 1132e32f2f54SBarry Smith if (fields[i] < 0) SETERRQ1(PETSC_COMM_SELF,PETSC_ERR_ARG_OUTOFRANGE,"Negative field %D requested",fields[i]); 113351f519a2SBarry Smith } 1134b00a9115SJed Brown ierr = PetscNew(&ilink);CHKERRQ(ierr); 1135a04f6461SBarry Smith if (splitname) { 1136db4c96c1SJed Brown ierr = PetscStrallocpy(splitname,&ilink->splitname);CHKERRQ(ierr); 1137a04f6461SBarry Smith } else { 1138785e854fSJed Brown ierr = PetscMalloc1(3,&ilink->splitname);CHKERRQ(ierr); 1139a04f6461SBarry Smith ierr = PetscSNPrintf(ilink->splitname,2,"%s",jac->nsplits);CHKERRQ(ierr); 1140a04f6461SBarry Smith } 1141785e854fSJed Brown ierr = PetscMalloc1(n,&ilink->fields);CHKERRQ(ierr); 11425a9f2f41SSatish Balay ierr = PetscMemcpy(ilink->fields,fields,n*sizeof(PetscInt));CHKERRQ(ierr); 1143785e854fSJed Brown ierr = PetscMalloc1(n,&ilink->fields_col);CHKERRQ(ierr); 11445d4c12cdSJungho Lee ierr = PetscMemcpy(ilink->fields_col,fields_col,n*sizeof(PetscInt));CHKERRQ(ierr); 11452fa5cd67SKarl Rupp 11465a9f2f41SSatish Balay ilink->nfields = n; 11470298fd71SBarry Smith ilink->next = NULL; 1148ce94432eSBarry Smith ierr = KSPCreate(PetscObjectComm((PetscObject)pc),&ilink->ksp);CHKERRQ(ierr); 114920252d06SBarry Smith ierr = PetscObjectIncrementTabLevel((PetscObject)ilink->ksp,(PetscObject)pc,1);CHKERRQ(ierr); 11505a9f2f41SSatish Balay ierr = KSPSetType(ilink->ksp,KSPPREONLY);CHKERRQ(ierr); 11519005cf84SBarry Smith ierr = PetscLogObjectParent((PetscObject)pc,(PetscObject)ilink->ksp);CHKERRQ(ierr); 115269a612a9SBarry Smith 11538caf3d72SBarry Smith ierr = PetscSNPrintf(prefix,sizeof(prefix),"%sfieldsplit_%s_",((PetscObject)pc)->prefix ? ((PetscObject)pc)->prefix : "",ilink->splitname);CHKERRQ(ierr); 11545a9f2f41SSatish Balay ierr = KSPSetOptionsPrefix(ilink->ksp,prefix);CHKERRQ(ierr); 11550971522cSBarry Smith 11560971522cSBarry Smith if (!next) { 11575a9f2f41SSatish Balay jac->head = ilink; 11580298fd71SBarry Smith ilink->previous = NULL; 11590971522cSBarry Smith } else { 11600971522cSBarry Smith while (next->next) { 11610971522cSBarry Smith next = next->next; 11620971522cSBarry Smith } 11635a9f2f41SSatish Balay next->next = ilink; 116451f519a2SBarry Smith ilink->previous = next; 11650971522cSBarry Smith } 11660971522cSBarry Smith jac->nsplits++; 11670971522cSBarry Smith PetscFunctionReturn(0); 11680971522cSBarry Smith } 11690971522cSBarry Smith 1170e69d4d44SBarry Smith #undef __FUNCT__ 1171e69d4d44SBarry Smith #define __FUNCT__ "PCFieldSplitGetSubKSP_FieldSplit_Schur" 11721e6b0712SBarry Smith static PetscErrorCode PCFieldSplitGetSubKSP_FieldSplit_Schur(PC pc,PetscInt *n,KSP **subksp) 1173e69d4d44SBarry Smith { 1174e69d4d44SBarry Smith PC_FieldSplit *jac = (PC_FieldSplit*)pc->data; 1175e69d4d44SBarry Smith PetscErrorCode ierr; 1176e69d4d44SBarry Smith 1177e69d4d44SBarry Smith PetscFunctionBegin; 1178785e854fSJed Brown ierr = PetscMalloc1(jac->nsplits,subksp);CHKERRQ(ierr); 1179e69d4d44SBarry Smith ierr = MatSchurComplementGetKSP(jac->schur,*subksp);CHKERRQ(ierr); 11802fa5cd67SKarl Rupp 1181e69d4d44SBarry Smith (*subksp)[1] = jac->kspschur; 118213e0d083SBarry Smith if (n) *n = jac->nsplits; 1183e69d4d44SBarry Smith PetscFunctionReturn(0); 1184e69d4d44SBarry Smith } 11850971522cSBarry Smith 11860971522cSBarry Smith #undef __FUNCT__ 118769a612a9SBarry Smith #define __FUNCT__ "PCFieldSplitGetSubKSP_FieldSplit" 11881e6b0712SBarry Smith static PetscErrorCode PCFieldSplitGetSubKSP_FieldSplit(PC pc,PetscInt *n,KSP **subksp) 11890971522cSBarry Smith { 11900971522cSBarry Smith PC_FieldSplit *jac = (PC_FieldSplit*)pc->data; 11910971522cSBarry Smith PetscErrorCode ierr; 11920971522cSBarry Smith PetscInt cnt = 0; 11935a9f2f41SSatish Balay PC_FieldSplitLink ilink = jac->head; 11940971522cSBarry Smith 11950971522cSBarry Smith PetscFunctionBegin; 1196785e854fSJed Brown ierr = PetscMalloc1(jac->nsplits,subksp);CHKERRQ(ierr); 11975a9f2f41SSatish Balay while (ilink) { 11985a9f2f41SSatish Balay (*subksp)[cnt++] = ilink->ksp; 11995a9f2f41SSatish Balay ilink = ilink->next; 12000971522cSBarry Smith } 12015d480477SMatthew G Knepley if (cnt != jac->nsplits) SETERRQ2(PETSC_COMM_SELF,PETSC_ERR_PLIB,"Corrupt PCFIELDSPLIT object: number of splits in linked list %D does not match number in object %D",cnt,jac->nsplits); 120213e0d083SBarry Smith if (n) *n = jac->nsplits; 12030971522cSBarry Smith PetscFunctionReturn(0); 12040971522cSBarry Smith } 12050971522cSBarry Smith 1206704ba839SBarry Smith #undef __FUNCT__ 1207704ba839SBarry Smith #define __FUNCT__ "PCFieldSplitSetIS_FieldSplit" 12081e6b0712SBarry Smith static PetscErrorCode PCFieldSplitSetIS_FieldSplit(PC pc,const char splitname[],IS is) 1209704ba839SBarry Smith { 1210704ba839SBarry Smith PC_FieldSplit *jac = (PC_FieldSplit*)pc->data; 1211704ba839SBarry Smith PetscErrorCode ierr; 1212704ba839SBarry Smith PC_FieldSplitLink ilink, next = jac->head; 1213704ba839SBarry Smith char prefix[128]; 1214704ba839SBarry Smith 1215704ba839SBarry Smith PetscFunctionBegin; 12166c924f48SJed Brown if (jac->splitdefined) { 12176c924f48SJed Brown ierr = PetscInfo1(pc,"Ignoring new split \"%s\" because the splits have already been defined\n",splitname);CHKERRQ(ierr); 12186c924f48SJed Brown PetscFunctionReturn(0); 12196c924f48SJed Brown } 1220b00a9115SJed Brown ierr = PetscNew(&ilink);CHKERRQ(ierr); 1221a04f6461SBarry Smith if (splitname) { 1222db4c96c1SJed Brown ierr = PetscStrallocpy(splitname,&ilink->splitname);CHKERRQ(ierr); 1223a04f6461SBarry Smith } else { 1224785e854fSJed Brown ierr = PetscMalloc1(8,&ilink->splitname);CHKERRQ(ierr); 1225b5787286SJed Brown ierr = PetscSNPrintf(ilink->splitname,7,"%D",jac->nsplits);CHKERRQ(ierr); 1226a04f6461SBarry Smith } 12271ab39975SBarry Smith ierr = PetscObjectReference((PetscObject)is);CHKERRQ(ierr); 1228b5787286SJed Brown ierr = ISDestroy(&ilink->is);CHKERRQ(ierr); 1229b5787286SJed Brown ilink->is = is; 1230b5787286SJed Brown ierr = PetscObjectReference((PetscObject)is);CHKERRQ(ierr); 1231b5787286SJed Brown ierr = ISDestroy(&ilink->is_col);CHKERRQ(ierr); 1232b5787286SJed Brown ilink->is_col = is; 12330298fd71SBarry Smith ilink->next = NULL; 1234ce94432eSBarry Smith ierr = KSPCreate(PetscObjectComm((PetscObject)pc),&ilink->ksp);CHKERRQ(ierr); 123520252d06SBarry Smith ierr = PetscObjectIncrementTabLevel((PetscObject)ilink->ksp,(PetscObject)pc,1);CHKERRQ(ierr); 1236704ba839SBarry Smith ierr = KSPSetType(ilink->ksp,KSPPREONLY);CHKERRQ(ierr); 12379005cf84SBarry Smith ierr = PetscLogObjectParent((PetscObject)pc,(PetscObject)ilink->ksp);CHKERRQ(ierr); 1238704ba839SBarry Smith 12398caf3d72SBarry Smith ierr = PetscSNPrintf(prefix,sizeof(prefix),"%sfieldsplit_%s_",((PetscObject)pc)->prefix ? ((PetscObject)pc)->prefix : "",ilink->splitname);CHKERRQ(ierr); 1240704ba839SBarry Smith ierr = KSPSetOptionsPrefix(ilink->ksp,prefix);CHKERRQ(ierr); 1241704ba839SBarry Smith 1242704ba839SBarry Smith if (!next) { 1243704ba839SBarry Smith jac->head = ilink; 12440298fd71SBarry Smith ilink->previous = NULL; 1245704ba839SBarry Smith } else { 1246704ba839SBarry Smith while (next->next) { 1247704ba839SBarry Smith next = next->next; 1248704ba839SBarry Smith } 1249704ba839SBarry Smith next->next = ilink; 1250704ba839SBarry Smith ilink->previous = next; 1251704ba839SBarry Smith } 1252704ba839SBarry Smith jac->nsplits++; 1253704ba839SBarry Smith PetscFunctionReturn(0); 1254704ba839SBarry Smith } 1255704ba839SBarry Smith 12560971522cSBarry Smith #undef __FUNCT__ 12570971522cSBarry Smith #define __FUNCT__ "PCFieldSplitSetFields" 12580971522cSBarry Smith /*@ 12590971522cSBarry Smith PCFieldSplitSetFields - Sets the fields for one particular split in the field split preconditioner 12600971522cSBarry Smith 1261ad4df100SBarry Smith Logically Collective on PC 12620971522cSBarry Smith 12630971522cSBarry Smith Input Parameters: 12640971522cSBarry Smith + pc - the preconditioner context 12650298fd71SBarry Smith . splitname - name of this split, if NULL the number of the split is used 12660971522cSBarry Smith . n - the number of fields in this split 1267db4c96c1SJed Brown - fields - the fields in this split 12680971522cSBarry Smith 12690971522cSBarry Smith Level: intermediate 12700971522cSBarry Smith 1271d32f9abdSBarry Smith Notes: Use PCFieldSplitSetIS() to set a completely general set of indices as a field. 1272d32f9abdSBarry Smith 12737287d2a3SDmitry Karpeev The PCFieldSplitSetFields() is for defining fields as strided blocks. For example, if the block 1274d32f9abdSBarry 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 1275d32f9abdSBarry Smith 0xx3xx6xx9xx12 ... x1xx4xx7xx ... xx2xx5xx8xx.. 01x34x67x... 0x1x3x5x7.. x12x45x78x.... 1276d32f9abdSBarry Smith where the numbered entries indicate what is in the field. 1277d32f9abdSBarry Smith 1278db4c96c1SJed Brown This function is called once per split (it creates a new split each time). Solve options 1279db4c96c1SJed Brown for this split will be available under the prefix -fieldsplit_SPLITNAME_. 1280db4c96c1SJed Brown 12815d4c12cdSJungho Lee Developer Note: This routine does not actually create the IS representing the split, that is delayed 12825d4c12cdSJungho Lee until PCSetUp_FieldSplit(), because information about the vector/matrix layouts may not be 12835d4c12cdSJungho Lee available when this routine is called. 12845d4c12cdSJungho Lee 1285d32f9abdSBarry Smith .seealso: PCFieldSplitGetSubKSP(), PCFIELDSPLIT, PCFieldSplitSetBlockSize(), PCFieldSplitSetIS() 12860971522cSBarry Smith 12870971522cSBarry Smith @*/ 12885d4c12cdSJungho Lee PetscErrorCode PCFieldSplitSetFields(PC pc,const char splitname[],PetscInt n,const PetscInt *fields,const PetscInt *fields_col) 12890971522cSBarry Smith { 12904ac538c5SBarry Smith PetscErrorCode ierr; 12910971522cSBarry Smith 12920971522cSBarry Smith PetscFunctionBegin; 12930700a824SBarry Smith PetscValidHeaderSpecific(pc,PC_CLASSID,1); 1294db4c96c1SJed Brown PetscValidCharPointer(splitname,2); 1295ce94432eSBarry Smith if (n < 1) SETERRQ2(PetscObjectComm((PetscObject)pc),PETSC_ERR_ARG_OUTOFRANGE,"Provided number of fields %D in split \"%s\" not positive",n,splitname); 1296db4c96c1SJed Brown PetscValidIntPointer(fields,3); 12975d4c12cdSJungho Lee ierr = PetscTryMethod(pc,"PCFieldSplitSetFields_C",(PC,const char[],PetscInt,const PetscInt*,const PetscInt*),(pc,splitname,n,fields,fields_col));CHKERRQ(ierr); 12980971522cSBarry Smith PetscFunctionReturn(0); 12990971522cSBarry Smith } 13000971522cSBarry Smith 13010971522cSBarry Smith #undef __FUNCT__ 1302704ba839SBarry Smith #define __FUNCT__ "PCFieldSplitSetIS" 1303704ba839SBarry Smith /*@ 1304704ba839SBarry Smith PCFieldSplitSetIS - Sets the exact elements for field 1305704ba839SBarry Smith 1306ad4df100SBarry Smith Logically Collective on PC 1307704ba839SBarry Smith 1308704ba839SBarry Smith Input Parameters: 1309704ba839SBarry Smith + pc - the preconditioner context 13100298fd71SBarry Smith . splitname - name of this split, if NULL the number of the split is used 1311db4c96c1SJed Brown - is - the index set that defines the vector elements in this field 1312704ba839SBarry Smith 1313d32f9abdSBarry Smith 1314a6ffb8dbSJed Brown Notes: 1315a6ffb8dbSJed Brown Use PCFieldSplitSetFields(), for fields defined by strided types. 1316a6ffb8dbSJed Brown 1317db4c96c1SJed Brown This function is called once per split (it creates a new split each time). Solve options 1318db4c96c1SJed Brown for this split will be available under the prefix -fieldsplit_SPLITNAME_. 1319d32f9abdSBarry Smith 1320704ba839SBarry Smith Level: intermediate 1321704ba839SBarry Smith 1322704ba839SBarry Smith .seealso: PCFieldSplitGetSubKSP(), PCFIELDSPLIT, PCFieldSplitSetBlockSize() 1323704ba839SBarry Smith 1324704ba839SBarry Smith @*/ 13257087cfbeSBarry Smith PetscErrorCode PCFieldSplitSetIS(PC pc,const char splitname[],IS is) 1326704ba839SBarry Smith { 13274ac538c5SBarry Smith PetscErrorCode ierr; 1328704ba839SBarry Smith 1329704ba839SBarry Smith PetscFunctionBegin; 13300700a824SBarry Smith PetscValidHeaderSpecific(pc,PC_CLASSID,1); 13317b62db95SJungho Lee if (splitname) PetscValidCharPointer(splitname,2); 1332db4c96c1SJed Brown PetscValidHeaderSpecific(is,IS_CLASSID,3); 13334ac538c5SBarry Smith ierr = PetscTryMethod(pc,"PCFieldSplitSetIS_C",(PC,const char[],IS),(pc,splitname,is));CHKERRQ(ierr); 1334704ba839SBarry Smith PetscFunctionReturn(0); 1335704ba839SBarry Smith } 1336704ba839SBarry Smith 1337704ba839SBarry Smith #undef __FUNCT__ 133857a9adfeSMatthew G Knepley #define __FUNCT__ "PCFieldSplitGetIS" 133957a9adfeSMatthew G Knepley /*@ 134057a9adfeSMatthew G Knepley PCFieldSplitGetIS - Retrieves the elements for a field as an IS 134157a9adfeSMatthew G Knepley 134257a9adfeSMatthew G Knepley Logically Collective on PC 134357a9adfeSMatthew G Knepley 134457a9adfeSMatthew G Knepley Input Parameters: 134557a9adfeSMatthew G Knepley + pc - the preconditioner context 134657a9adfeSMatthew G Knepley - splitname - name of this split 134757a9adfeSMatthew G Knepley 134857a9adfeSMatthew G Knepley Output Parameter: 13490298fd71SBarry Smith - is - the index set that defines the vector elements in this field, or NULL if the field is not found 135057a9adfeSMatthew G Knepley 135157a9adfeSMatthew G Knepley Level: intermediate 135257a9adfeSMatthew G Knepley 135357a9adfeSMatthew G Knepley .seealso: PCFieldSplitGetSubKSP(), PCFIELDSPLIT, PCFieldSplitSetIS() 135457a9adfeSMatthew G Knepley 135557a9adfeSMatthew G Knepley @*/ 135657a9adfeSMatthew G Knepley PetscErrorCode PCFieldSplitGetIS(PC pc,const char splitname[],IS *is) 135757a9adfeSMatthew G Knepley { 135857a9adfeSMatthew G Knepley PetscErrorCode ierr; 135957a9adfeSMatthew G Knepley 136057a9adfeSMatthew G Knepley PetscFunctionBegin; 136157a9adfeSMatthew G Knepley PetscValidHeaderSpecific(pc,PC_CLASSID,1); 136257a9adfeSMatthew G Knepley PetscValidCharPointer(splitname,2); 136357a9adfeSMatthew G Knepley PetscValidPointer(is,3); 136457a9adfeSMatthew G Knepley { 136557a9adfeSMatthew G Knepley PC_FieldSplit *jac = (PC_FieldSplit*) pc->data; 136657a9adfeSMatthew G Knepley PC_FieldSplitLink ilink = jac->head; 136757a9adfeSMatthew G Knepley PetscBool found; 136857a9adfeSMatthew G Knepley 13690298fd71SBarry Smith *is = NULL; 137057a9adfeSMatthew G Knepley while (ilink) { 137157a9adfeSMatthew G Knepley ierr = PetscStrcmp(ilink->splitname, splitname, &found);CHKERRQ(ierr); 137257a9adfeSMatthew G Knepley if (found) { 137357a9adfeSMatthew G Knepley *is = ilink->is; 137457a9adfeSMatthew G Knepley break; 137557a9adfeSMatthew G Knepley } 137657a9adfeSMatthew G Knepley ilink = ilink->next; 137757a9adfeSMatthew G Knepley } 137857a9adfeSMatthew G Knepley } 137957a9adfeSMatthew G Knepley PetscFunctionReturn(0); 138057a9adfeSMatthew G Knepley } 138157a9adfeSMatthew G Knepley 138257a9adfeSMatthew G Knepley #undef __FUNCT__ 138351f519a2SBarry Smith #define __FUNCT__ "PCFieldSplitSetBlockSize" 138451f519a2SBarry Smith /*@ 138551f519a2SBarry Smith PCFieldSplitSetBlockSize - Sets the block size for defining where fields start in the 138651f519a2SBarry Smith fieldsplit preconditioner. If not set the matrix block size is used. 138751f519a2SBarry Smith 1388ad4df100SBarry Smith Logically Collective on PC 138951f519a2SBarry Smith 139051f519a2SBarry Smith Input Parameters: 139151f519a2SBarry Smith + pc - the preconditioner context 139251f519a2SBarry Smith - bs - the block size 139351f519a2SBarry Smith 139451f519a2SBarry Smith Level: intermediate 139551f519a2SBarry Smith 139651f519a2SBarry Smith .seealso: PCFieldSplitGetSubKSP(), PCFIELDSPLIT, PCFieldSplitSetFields() 139751f519a2SBarry Smith 139851f519a2SBarry Smith @*/ 13997087cfbeSBarry Smith PetscErrorCode PCFieldSplitSetBlockSize(PC pc,PetscInt bs) 140051f519a2SBarry Smith { 14014ac538c5SBarry Smith PetscErrorCode ierr; 140251f519a2SBarry Smith 140351f519a2SBarry Smith PetscFunctionBegin; 14040700a824SBarry Smith PetscValidHeaderSpecific(pc,PC_CLASSID,1); 1405c5eb9154SBarry Smith PetscValidLogicalCollectiveInt(pc,bs,2); 14064ac538c5SBarry Smith ierr = PetscTryMethod(pc,"PCFieldSplitSetBlockSize_C",(PC,PetscInt),(pc,bs));CHKERRQ(ierr); 140751f519a2SBarry Smith PetscFunctionReturn(0); 140851f519a2SBarry Smith } 140951f519a2SBarry Smith 141051f519a2SBarry Smith #undef __FUNCT__ 141169a612a9SBarry Smith #define __FUNCT__ "PCFieldSplitGetSubKSP" 14120971522cSBarry Smith /*@C 141369a612a9SBarry Smith PCFieldSplitGetSubKSP - Gets the KSP contexts for all splits 14140971522cSBarry Smith 141569a612a9SBarry Smith Collective on KSP 14160971522cSBarry Smith 14170971522cSBarry Smith Input Parameter: 14180971522cSBarry Smith . pc - the preconditioner context 14190971522cSBarry Smith 14200971522cSBarry Smith Output Parameters: 142113e0d083SBarry Smith + n - the number of splits 142269a612a9SBarry Smith - pc - the array of KSP contexts 14230971522cSBarry Smith 14240971522cSBarry Smith Note: 1425d32f9abdSBarry Smith After PCFieldSplitGetSubKSP() the array of KSPs IS to be freed by the user 1426d32f9abdSBarry Smith (not the KSP just the array that contains them). 14270971522cSBarry Smith 142869a612a9SBarry Smith You must call KSPSetUp() before calling PCFieldSplitGetSubKSP(). 14290971522cSBarry Smith 1430196cc216SBarry Smith Fortran Usage: You must pass in a KSP array that is large enough to contain all the local KSPs. 14310298fd71SBarry Smith You can call PCFieldSplitGetSubKSP(pc,n,NULL_OBJECT,ierr) to determine how large the 1432196cc216SBarry Smith KSP array must be. 1433196cc216SBarry Smith 1434196cc216SBarry Smith 14350971522cSBarry Smith Level: advanced 14360971522cSBarry Smith 14370971522cSBarry Smith .seealso: PCFIELDSPLIT 14380971522cSBarry Smith @*/ 14397087cfbeSBarry Smith PetscErrorCode PCFieldSplitGetSubKSP(PC pc,PetscInt *n,KSP *subksp[]) 14400971522cSBarry Smith { 14414ac538c5SBarry Smith PetscErrorCode ierr; 14420971522cSBarry Smith 14430971522cSBarry Smith PetscFunctionBegin; 14440700a824SBarry Smith PetscValidHeaderSpecific(pc,PC_CLASSID,1); 144513e0d083SBarry Smith if (n) PetscValidIntPointer(n,2); 14464ac538c5SBarry Smith ierr = PetscUseMethod(pc,"PCFieldSplitGetSubKSP_C",(PC,PetscInt*,KSP **),(pc,n,subksp));CHKERRQ(ierr); 14470971522cSBarry Smith PetscFunctionReturn(0); 14480971522cSBarry Smith } 14490971522cSBarry Smith 1450e69d4d44SBarry Smith #undef __FUNCT__ 1451e69d4d44SBarry Smith #define __FUNCT__ "PCFieldSplitSchurPrecondition" 1452e69d4d44SBarry Smith /*@ 1453e69d4d44SBarry Smith PCFieldSplitSchurPrecondition - Indicates if the Schur complement is preconditioned by a preconditioner constructed by the 1454a04f6461SBarry Smith A11 matrix. Otherwise no preconditioner is used. 1455e69d4d44SBarry Smith 1456e69d4d44SBarry Smith Collective on PC 1457e69d4d44SBarry Smith 1458e69d4d44SBarry Smith Input Parameters: 1459e69d4d44SBarry Smith + pc - the preconditioner context 1460a7476a74SDmitry Karpeev . ptype - which matrix to use for preconditioning the Schur complement: PC_FIELDSPLIT_SCHUR_PRE_A11 (default), PC_FIELDSPLIT_SCHUR_PRE_SELF, PC_FIELDSPLIT_PRE_USER 14610298fd71SBarry Smith - userpre - matrix to use for preconditioning, or NULL 1462084e4875SJed Brown 1463e69d4d44SBarry Smith Options Database: 1464a7476a74SDmitry Karpeev . -pc_fieldsplit_schur_precondition <self,selfp,user,a11> default is a11 1465e69d4d44SBarry Smith 1466fd1303e9SJungho Lee Notes: 1467fd1303e9SJungho Lee $ If ptype is 1468fd1303e9SJungho Lee $ user then the preconditioner for the Schur complement is generated by the provided matrix (pre argument 1469fd1303e9SJungho Lee $ to this function). 1470e87fab1bSBarry Smith $ a11 then the preconditioner for the Schur complement is generated by the block diagonal part of the original 1471fd1303e9SJungho Lee $ matrix associated with the Schur complement (i.e. A11) 1472fd1303e9SJungho Lee $ self the preconditioner for the Schur complement is generated from the Schur complement matrix itself: 1473fd1303e9SJungho Lee $ The only preconditioner that currently works directly with the Schur complement matrix object is the PCLSC 1474fd1303e9SJungho Lee $ preconditioner 1475a7476a74SDmitry Karpeev $ selfp then the preconditioning matrix is an explicitly-assembled approximation Sp = A11 - A10 inv(diag(A00)) A01 1476a7476a74SDmitry Karpeev $ This is only a good preconditioner when diag(A00) is a good preconditioner for A00. 1477fd1303e9SJungho Lee 1478e87fab1bSBarry Smith When solving a saddle point problem, where the A11 block is identically zero, using a11 as the ptype only makes sense 1479fd1303e9SJungho Lee with the additional option -fieldsplit_1_pc_type none. Usually for saddle point problems one would use a ptype of self and 1480a7476a74SDmitry Karpeev -fieldsplit_1_pc_type lsc which uses the least squares commutator to compute a preconditioner for the Schur complement. 1481fd1303e9SJungho Lee 1482a7476a74SDmitry Karpeev Developer Notes: This is a terrible name, which gives no good indication of what the function does. 1483a7476a74SDmitry Karpeev Among other things, it should have 'Set' in the name, since it sets the type of matrix to use. 1484fd1303e9SJungho Lee 1485e69d4d44SBarry Smith Level: intermediate 1486e69d4d44SBarry Smith 1487fd1303e9SJungho Lee .seealso: PCFieldSplitGetSubKSP(), PCFIELDSPLIT, PCFieldSplitSetFields(), PCFieldSplitSchurPreType, PCLSC 1488e69d4d44SBarry Smith 1489e69d4d44SBarry Smith @*/ 14907087cfbeSBarry Smith PetscErrorCode PCFieldSplitSchurPrecondition(PC pc,PCFieldSplitSchurPreType ptype,Mat pre) 1491e69d4d44SBarry Smith { 14924ac538c5SBarry Smith PetscErrorCode ierr; 1493e69d4d44SBarry Smith 1494e69d4d44SBarry Smith PetscFunctionBegin; 14950700a824SBarry Smith PetscValidHeaderSpecific(pc,PC_CLASSID,1); 14964ac538c5SBarry Smith ierr = PetscTryMethod(pc,"PCFieldSplitSchurPrecondition_C",(PC,PCFieldSplitSchurPreType,Mat),(pc,ptype,pre));CHKERRQ(ierr); 1497e69d4d44SBarry Smith PetscFunctionReturn(0); 1498e69d4d44SBarry Smith } 1499e69d4d44SBarry Smith 1500e69d4d44SBarry Smith #undef __FUNCT__ 1501*45e7fc46SDmitry Karpeev #define __FUNCT__ "PCFieldSplitSchurSetSelfpLumping" 1502*45e7fc46SDmitry Karpeev /*@ 1503*45e7fc46SDmitry Karpeev PCFieldSplitSchurSetSelfpLumping - Indicates whether the Schur complement preconditioner matrix 'selfp' is to be assembled 1504*45e7fc46SDmitry Karpeev using a row-lumped A00 matrix. 1505*45e7fc46SDmitry Karpeev 1506*45e7fc46SDmitry Karpeev Not collective 1507*45e7fc46SDmitry Karpeev 1508*45e7fc46SDmitry Karpeev Input Parameters: 1509*45e7fc46SDmitry Karpeev + pc - the preconditioner context 1510*45e7fc46SDmitry Karpeev - lump - whether to lump A00 when forming Sp = A11 - A10 inv(diag(A00)) A01 1511*45e7fc46SDmitry Karpeev 1512*45e7fc46SDmitry Karpeev Options Database: 1513*45e7fc46SDmitry Karpeev + -pc_fieldsplit_schur_precondition_selfp_lump 1514*45e7fc46SDmitry Karpeev . Only used with -pc_fieldsplit_schur_precondition selfp or programmatic equivalent PCFieldSplitSchurSetSelfLumping() 1515*45e7fc46SDmitry Karpeev - Default is PETSC_FALSE. 1516*45e7fc46SDmitry Karpeev 1517*45e7fc46SDmitry Karpeev 1518*45e7fc46SDmitry Karpeev Level: advanced 1519*45e7fc46SDmitry Karpeev 1520*45e7fc46SDmitry Karpeev .seealso: PCFieldSplitGetSubKSP(), PCFIELDSPLIT, PCFieldSplitSchurPreType, PCFieldSplitSchurPrecondition(), PCFieldSplitSchurGetSelfpLumping() 1521*45e7fc46SDmitry Karpeev 1522*45e7fc46SDmitry Karpeev @*/ 1523*45e7fc46SDmitry Karpeev PetscErrorCode PCFieldSplitSchurSetSelfpLumping(PC pc,PetscBool lump) 1524*45e7fc46SDmitry Karpeev { 1525*45e7fc46SDmitry Karpeev PetscErrorCode ierr; 1526*45e7fc46SDmitry Karpeev const char* t; 1527*45e7fc46SDmitry Karpeev PetscBool isfs; 1528*45e7fc46SDmitry Karpeev PC_FieldSplit *jac; 1529*45e7fc46SDmitry Karpeev 1530*45e7fc46SDmitry Karpeev PetscFunctionBegin; 1531*45e7fc46SDmitry Karpeev PetscValidHeaderSpecific(pc,PC_CLASSID,1); 1532*45e7fc46SDmitry Karpeev ierr = PetscObjectGetType((PetscObject)pc,&t);CHKERRQ(ierr); 1533*45e7fc46SDmitry Karpeev ierr = PetscStrcmp(t,PCFIELDSPLIT,&isfs);CHKERRQ(ierr); 1534*45e7fc46SDmitry Karpeev if (!isfs) SETERRQ1(PETSC_COMM_SELF,PETSC_ERR_ARG_WRONG,"Expected PC of type PCFIELDSPLIT, got %s instead",t); 1535*45e7fc46SDmitry Karpeev jac = (PC_FieldSplit*)pc->data; 1536*45e7fc46SDmitry Karpeev jac->schurp_lump = lump; 1537*45e7fc46SDmitry Karpeev PetscFunctionReturn(0); 1538*45e7fc46SDmitry Karpeev } 1539*45e7fc46SDmitry Karpeev 1540*45e7fc46SDmitry Karpeev #undef __FUNCT__ 1541*45e7fc46SDmitry Karpeev #define __FUNCT__ "PCFieldSplitSchurGetSelfpLumping" 1542*45e7fc46SDmitry Karpeev /*@ 1543*45e7fc46SDmitry Karpeev PCFieldSplitSchurGetSelfpLumping - Indicates whether the Schur complement preconditioner matrix 'selfp' is to be assembled 1544*45e7fc46SDmitry Karpeev using a row-lumped A00 matrix. 1545*45e7fc46SDmitry Karpeev 1546*45e7fc46SDmitry Karpeev Not collective 1547*45e7fc46SDmitry Karpeev 1548*45e7fc46SDmitry Karpeev Input Parameter: 1549*45e7fc46SDmitry Karpeev . pc - the preconditioner context 1550*45e7fc46SDmitry Karpeev 1551*45e7fc46SDmitry Karpeev Output Parameter: 1552*45e7fc46SDmitry Karpeev . lump - whether to lump A00 when forming Sp = A11 - A10 inv(diag(A00)) A01 1553*45e7fc46SDmitry Karpeev 1554*45e7fc46SDmitry Karpeev Options Database: 1555*45e7fc46SDmitry Karpeev + Only used with -pc_fieldsplit_schur_precondition selfp or programmatic equivalent PCFieldSplitSchurSetSelfLumping() 1556*45e7fc46SDmitry Karpeev - Default is PETSC_FALSE. 1557*45e7fc46SDmitry Karpeev 1558*45e7fc46SDmitry Karpeev 1559*45e7fc46SDmitry Karpeev Level: advanced 1560*45e7fc46SDmitry Karpeev 1561*45e7fc46SDmitry Karpeev .seealso: PCFieldSplitGetSubKSP(), PCFIELDSPLIT, PCFieldSplitSchurPreType, PCFieldSplitSchurPrecondition(), PCFieldSplitSchurSetSelfpLumping() 1562*45e7fc46SDmitry Karpeev 1563*45e7fc46SDmitry Karpeev @*/ 1564*45e7fc46SDmitry Karpeev PetscErrorCode PCFieldSplitSchurGetSelfpLumping(PC pc,PetscBool *lump) 1565*45e7fc46SDmitry Karpeev { 1566*45e7fc46SDmitry Karpeev PetscErrorCode ierr; 1567*45e7fc46SDmitry Karpeev const char* t; 1568*45e7fc46SDmitry Karpeev PetscBool isfs; 1569*45e7fc46SDmitry Karpeev PC_FieldSplit *jac; 1570*45e7fc46SDmitry Karpeev 1571*45e7fc46SDmitry Karpeev PetscFunctionBegin; 1572*45e7fc46SDmitry Karpeev PetscValidHeaderSpecific(pc,PC_CLASSID,1); 1573*45e7fc46SDmitry Karpeev ierr = PetscObjectGetType((PetscObject)pc,&t);CHKERRQ(ierr); 1574*45e7fc46SDmitry Karpeev ierr = PetscStrcmp(t,PCFIELDSPLIT,&isfs);CHKERRQ(ierr); 1575*45e7fc46SDmitry Karpeev if (!isfs) SETERRQ1(PETSC_COMM_SELF,PETSC_ERR_ARG_WRONG,"Expected PC of type PCFIELDSPLIT, got %s instead",t); 1576*45e7fc46SDmitry Karpeev jac = (PC_FieldSplit*)pc->data; 1577*45e7fc46SDmitry Karpeev if (lump) *lump = jac->schurp_lump; 1578*45e7fc46SDmitry Karpeev PetscFunctionReturn(0); 1579*45e7fc46SDmitry Karpeev } 1580*45e7fc46SDmitry Karpeev 1581*45e7fc46SDmitry Karpeev #undef __FUNCT__ 1582e69d4d44SBarry Smith #define __FUNCT__ "PCFieldSplitSchurPrecondition_FieldSplit" 15831e6b0712SBarry Smith static PetscErrorCode PCFieldSplitSchurPrecondition_FieldSplit(PC pc,PCFieldSplitSchurPreType ptype,Mat pre) 1584e69d4d44SBarry Smith { 1585e69d4d44SBarry Smith PC_FieldSplit *jac = (PC_FieldSplit*)pc->data; 1586084e4875SJed Brown PetscErrorCode ierr; 1587e69d4d44SBarry Smith 1588e69d4d44SBarry Smith PetscFunctionBegin; 1589084e4875SJed Brown jac->schurpre = ptype; 1590a7476a74SDmitry Karpeev if (ptype == PC_FIELDSPLIT_SCHUR_PRE_USER && pre) { 15916bf464f9SBarry Smith ierr = MatDestroy(&jac->schur_user);CHKERRQ(ierr); 1592084e4875SJed Brown jac->schur_user = pre; 1593084e4875SJed Brown ierr = PetscObjectReference((PetscObject)jac->schur_user);CHKERRQ(ierr); 1594084e4875SJed Brown } 1595e69d4d44SBarry Smith PetscFunctionReturn(0); 1596e69d4d44SBarry Smith } 1597e69d4d44SBarry Smith 159830ad9308SMatthew Knepley #undef __FUNCT__ 1599c9c6ffaaSJed Brown #define __FUNCT__ "PCFieldSplitSetSchurFactType" 1600ab1df9f5SJed Brown /*@ 1601c9c6ffaaSJed Brown PCFieldSplitSetSchurFactType - sets which blocks of the approximate block factorization to retain 1602ab1df9f5SJed Brown 1603ab1df9f5SJed Brown Collective on PC 1604ab1df9f5SJed Brown 1605ab1df9f5SJed Brown Input Parameters: 1606ab1df9f5SJed Brown + pc - the preconditioner context 1607c9c6ffaaSJed Brown - ftype - which blocks of factorization to retain, PC_FIELDSPLIT_SCHUR_FACT_FULL is default 1608ab1df9f5SJed Brown 1609ab1df9f5SJed Brown Options Database: 1610c9c6ffaaSJed Brown . -pc_fieldsplit_schur_fact_type <diag,lower,upper,full> default is full 1611ab1df9f5SJed Brown 1612ab1df9f5SJed Brown 1613ab1df9f5SJed Brown Level: intermediate 1614ab1df9f5SJed Brown 1615ab1df9f5SJed Brown Notes: 1616ab1df9f5SJed Brown The FULL factorization is 1617ab1df9f5SJed Brown 1618ab1df9f5SJed Brown $ (A B) = (1 0) (A 0) (1 Ainv*B) 1619ab1df9f5SJed Brown $ (C D) (C*Ainv 1) (0 S) (0 1 ) 1620ab1df9f5SJed Brown 16216be4592eSBarry Smith where S = D - C*Ainv*B. In practice, the full factorization is applied via block triangular solves with the grouping L*(D*U). UPPER uses D*U, LOWER uses L*D, 16226be4592eSBarry Smith and DIAG is the diagonal part with the sign of S flipped (because this makes the preconditioner positive definite for many formulations, thus allowing the use of KSPMINRES). 1623ab1df9f5SJed Brown 16246be4592eSBarry Smith If applied exactly, FULL factorization is a direct solver. The preconditioned operator with LOWER or UPPER has all eigenvalues equal to 1 and minimal polynomial 16256be4592eSBarry Smith of degree 2, so KSPGMRES converges in 2 iterations. If the iteration count is very low, consider using KSPFGMRES or KSPGCR which can use one less preconditioner 16266be4592eSBarry Smith application in this case. Note that the preconditioned operator may be highly non-normal, so such fast convergence may not be observed in practice. With DIAG, 16276be4592eSBarry Smith the preconditioned operator has three distinct nonzero eigenvalues and minimal polynomial of degree at most 4, so KSPGMRES converges in at most 4 iterations. 1628ab1df9f5SJed Brown 16296be4592eSBarry Smith For symmetric problems in which A is positive definite and S is negative definite, DIAG can be used with KSPMINRES. Note that a flexible method like KSPFGMRES 16306be4592eSBarry Smith or KSPGCR must be used if the fieldsplit preconditioner is nonlinear (e.g. a few iterations of a Krylov method is used inside a split). 1631ab1df9f5SJed Brown 1632ab1df9f5SJed Brown References: 1633ab1df9f5SJed Brown Murphy, Golub, and Wathen, A note on preconditioning indefinite linear systems, SIAM J. Sci. Comput., 21 (2000) pp. 1969-1972. 1634ab1df9f5SJed Brown 1635ab1df9f5SJed Brown Ipsen, A note on preconditioning nonsymmetric matrices, SIAM J. Sci. Comput., 23 (2001), pp. 1050-1051. 1636ab1df9f5SJed Brown 1637ab1df9f5SJed Brown .seealso: PCFieldSplitGetSubKSP(), PCFIELDSPLIT, PCFieldSplitSetFields(), PCFieldSplitSchurPreType 1638ab1df9f5SJed Brown @*/ 1639c9c6ffaaSJed Brown PetscErrorCode PCFieldSplitSetSchurFactType(PC pc,PCFieldSplitSchurFactType ftype) 1640ab1df9f5SJed Brown { 1641ab1df9f5SJed Brown PetscErrorCode ierr; 1642ab1df9f5SJed Brown 1643ab1df9f5SJed Brown PetscFunctionBegin; 1644ab1df9f5SJed Brown PetscValidHeaderSpecific(pc,PC_CLASSID,1); 1645c9c6ffaaSJed Brown ierr = PetscTryMethod(pc,"PCFieldSplitSetSchurFactType_C",(PC,PCFieldSplitSchurFactType),(pc,ftype));CHKERRQ(ierr); 1646ab1df9f5SJed Brown PetscFunctionReturn(0); 1647ab1df9f5SJed Brown } 1648ab1df9f5SJed Brown 1649ab1df9f5SJed Brown #undef __FUNCT__ 1650c9c6ffaaSJed Brown #define __FUNCT__ "PCFieldSplitSetSchurFactType_FieldSplit" 16511e6b0712SBarry Smith static PetscErrorCode PCFieldSplitSetSchurFactType_FieldSplit(PC pc,PCFieldSplitSchurFactType ftype) 1652ab1df9f5SJed Brown { 1653ab1df9f5SJed Brown PC_FieldSplit *jac = (PC_FieldSplit*)pc->data; 1654ab1df9f5SJed Brown 1655ab1df9f5SJed Brown PetscFunctionBegin; 1656ab1df9f5SJed Brown jac->schurfactorization = ftype; 1657ab1df9f5SJed Brown PetscFunctionReturn(0); 1658ab1df9f5SJed Brown } 1659ab1df9f5SJed Brown 1660ab1df9f5SJed Brown #undef __FUNCT__ 166130ad9308SMatthew Knepley #define __FUNCT__ "PCFieldSplitGetSchurBlocks" 166230ad9308SMatthew Knepley /*@C 16638c03b21aSDmitry Karpeev PCFieldSplitGetSchurBlocks - Gets all matrix blocks for the Schur complement 166430ad9308SMatthew Knepley 166530ad9308SMatthew Knepley Collective on KSP 166630ad9308SMatthew Knepley 166730ad9308SMatthew Knepley Input Parameter: 166830ad9308SMatthew Knepley . pc - the preconditioner context 166930ad9308SMatthew Knepley 167030ad9308SMatthew Knepley Output Parameters: 1671a04f6461SBarry Smith + A00 - the (0,0) block 1672a04f6461SBarry Smith . A01 - the (0,1) block 1673a04f6461SBarry Smith . A10 - the (1,0) block 1674a04f6461SBarry Smith - A11 - the (1,1) block 167530ad9308SMatthew Knepley 167630ad9308SMatthew Knepley Level: advanced 167730ad9308SMatthew Knepley 167830ad9308SMatthew Knepley .seealso: PCFIELDSPLIT 167930ad9308SMatthew Knepley @*/ 1680a04f6461SBarry Smith PetscErrorCode PCFieldSplitGetSchurBlocks(PC pc,Mat *A00,Mat *A01,Mat *A10, Mat *A11) 168130ad9308SMatthew Knepley { 168230ad9308SMatthew Knepley PC_FieldSplit *jac = (PC_FieldSplit*) pc->data; 168330ad9308SMatthew Knepley 168430ad9308SMatthew Knepley PetscFunctionBegin; 16850700a824SBarry Smith PetscValidHeaderSpecific(pc,PC_CLASSID,1); 1686ce94432eSBarry Smith if (jac->type != PC_COMPOSITE_SCHUR) SETERRQ(PetscObjectComm((PetscObject)pc),PETSC_ERR_ARG_WRONG, "FieldSplit is not using a Schur complement approach."); 1687a04f6461SBarry Smith if (A00) *A00 = jac->pmat[0]; 1688a04f6461SBarry Smith if (A01) *A01 = jac->B; 1689a04f6461SBarry Smith if (A10) *A10 = jac->C; 1690a04f6461SBarry Smith if (A11) *A11 = jac->pmat[1]; 169130ad9308SMatthew Knepley PetscFunctionReturn(0); 169230ad9308SMatthew Knepley } 169330ad9308SMatthew Knepley 169479416396SBarry Smith #undef __FUNCT__ 169579416396SBarry Smith #define __FUNCT__ "PCFieldSplitSetType_FieldSplit" 16961e6b0712SBarry Smith static PetscErrorCode PCFieldSplitSetType_FieldSplit(PC pc,PCCompositeType type) 169779416396SBarry Smith { 169879416396SBarry Smith PC_FieldSplit *jac = (PC_FieldSplit*)pc->data; 1699e69d4d44SBarry Smith PetscErrorCode ierr; 170079416396SBarry Smith 170179416396SBarry Smith PetscFunctionBegin; 170279416396SBarry Smith jac->type = type; 17033b224e63SBarry Smith if (type == PC_COMPOSITE_SCHUR) { 17043b224e63SBarry Smith pc->ops->apply = PCApply_FieldSplit_Schur; 17053b224e63SBarry Smith pc->ops->view = PCView_FieldSplit_Schur; 17062fa5cd67SKarl Rupp 1707bdf89e91SBarry Smith ierr = PetscObjectComposeFunction((PetscObject)pc,"PCFieldSplitGetSubKSP_C",PCFieldSplitGetSubKSP_FieldSplit_Schur);CHKERRQ(ierr); 1708bdf89e91SBarry Smith ierr = PetscObjectComposeFunction((PetscObject)pc,"PCFieldSplitSchurPrecondition_C",PCFieldSplitSchurPrecondition_FieldSplit);CHKERRQ(ierr); 1709bdf89e91SBarry Smith ierr = PetscObjectComposeFunction((PetscObject)pc,"PCFieldSplitSetSchurFactType_C",PCFieldSplitSetSchurFactType_FieldSplit);CHKERRQ(ierr); 1710e69d4d44SBarry Smith 17113b224e63SBarry Smith } else { 17123b224e63SBarry Smith pc->ops->apply = PCApply_FieldSplit; 17133b224e63SBarry Smith pc->ops->view = PCView_FieldSplit; 17142fa5cd67SKarl Rupp 1715bdf89e91SBarry Smith ierr = PetscObjectComposeFunction((PetscObject)pc,"PCFieldSplitGetSubKSP_C",PCFieldSplitGetSubKSP_FieldSplit);CHKERRQ(ierr); 1716bdf89e91SBarry Smith ierr = PetscObjectComposeFunction((PetscObject)pc,"PCFieldSplitSchurPrecondition_C",0);CHKERRQ(ierr); 1717bdf89e91SBarry Smith ierr = PetscObjectComposeFunction((PetscObject)pc,"PCFieldSplitSetSchurFactType_C",0);CHKERRQ(ierr); 17183b224e63SBarry Smith } 171979416396SBarry Smith PetscFunctionReturn(0); 172079416396SBarry Smith } 172179416396SBarry Smith 172251f519a2SBarry Smith #undef __FUNCT__ 172351f519a2SBarry Smith #define __FUNCT__ "PCFieldSplitSetBlockSize_FieldSplit" 17241e6b0712SBarry Smith static PetscErrorCode PCFieldSplitSetBlockSize_FieldSplit(PC pc,PetscInt bs) 172551f519a2SBarry Smith { 172651f519a2SBarry Smith PC_FieldSplit *jac = (PC_FieldSplit*)pc->data; 172751f519a2SBarry Smith 172851f519a2SBarry Smith PetscFunctionBegin; 1729ce94432eSBarry Smith if (bs < 1) SETERRQ1(PetscObjectComm((PetscObject)pc),PETSC_ERR_ARG_OUTOFRANGE,"Blocksize must be positive, you gave %D",bs); 1730ce94432eSBarry Smith if (jac->bs > 0 && jac->bs != bs) SETERRQ2(PetscObjectComm((PetscObject)pc),PETSC_ERR_ARG_WRONGSTATE,"Cannot change fieldsplit blocksize from %D to %D after it has been set",jac->bs,bs); 173151f519a2SBarry Smith jac->bs = bs; 173251f519a2SBarry Smith PetscFunctionReturn(0); 173351f519a2SBarry Smith } 173451f519a2SBarry Smith 173579416396SBarry Smith #undef __FUNCT__ 173679416396SBarry Smith #define __FUNCT__ "PCFieldSplitSetType" 1737bc08b0f1SBarry Smith /*@ 173879416396SBarry Smith PCFieldSplitSetType - Sets the type of fieldsplit preconditioner. 173979416396SBarry Smith 174079416396SBarry Smith Collective on PC 174179416396SBarry Smith 174279416396SBarry Smith Input Parameter: 174379416396SBarry Smith . pc - the preconditioner context 174481540f2fSBarry Smith . type - PC_COMPOSITE_ADDITIVE, PC_COMPOSITE_MULTIPLICATIVE (default), PC_COMPOSITE_SYMMETRIC_MULTIPLICATIVE, PC_COMPOSITE_SPECIAL, PC_COMPOSITE_SCHUR 174579416396SBarry Smith 174679416396SBarry Smith Options Database Key: 1747a4efd8eaSMatthew Knepley . -pc_fieldsplit_type <type: one of multiplicative, additive, symmetric_multiplicative, special, schur> - Sets fieldsplit preconditioner type 174879416396SBarry Smith 1749b02e2d75SMatthew G Knepley Level: Intermediate 175079416396SBarry Smith 175179416396SBarry Smith .keywords: PC, set, type, composite preconditioner, additive, multiplicative 175279416396SBarry Smith 175379416396SBarry Smith .seealso: PCCompositeSetType() 175479416396SBarry Smith 175579416396SBarry Smith @*/ 17567087cfbeSBarry Smith PetscErrorCode PCFieldSplitSetType(PC pc,PCCompositeType type) 175779416396SBarry Smith { 17584ac538c5SBarry Smith PetscErrorCode ierr; 175979416396SBarry Smith 176079416396SBarry Smith PetscFunctionBegin; 17610700a824SBarry Smith PetscValidHeaderSpecific(pc,PC_CLASSID,1); 17624ac538c5SBarry Smith ierr = PetscTryMethod(pc,"PCFieldSplitSetType_C",(PC,PCCompositeType),(pc,type));CHKERRQ(ierr); 176379416396SBarry Smith PetscFunctionReturn(0); 176479416396SBarry Smith } 176579416396SBarry Smith 1766b02e2d75SMatthew G Knepley #undef __FUNCT__ 1767b02e2d75SMatthew G Knepley #define __FUNCT__ "PCFieldSplitGetType" 1768b02e2d75SMatthew G Knepley /*@ 1769b02e2d75SMatthew G Knepley PCFieldSplitGetType - Gets the type of fieldsplit preconditioner. 1770b02e2d75SMatthew G Knepley 1771b02e2d75SMatthew G Knepley Not collective 1772b02e2d75SMatthew G Knepley 1773b02e2d75SMatthew G Knepley Input Parameter: 1774b02e2d75SMatthew G Knepley . pc - the preconditioner context 1775b02e2d75SMatthew G Knepley 1776b02e2d75SMatthew G Knepley Output Parameter: 1777b02e2d75SMatthew G Knepley . type - PC_COMPOSITE_ADDITIVE, PC_COMPOSITE_MULTIPLICATIVE (default), PC_COMPOSITE_SYMMETRIC_MULTIPLICATIVE, PC_COMPOSITE_SPECIAL, PC_COMPOSITE_SCHUR 1778b02e2d75SMatthew G Knepley 1779b02e2d75SMatthew G Knepley Level: Intermediate 1780b02e2d75SMatthew G Knepley 1781b02e2d75SMatthew G Knepley .keywords: PC, set, type, composite preconditioner, additive, multiplicative 1782b02e2d75SMatthew G Knepley .seealso: PCCompositeSetType() 1783b02e2d75SMatthew G Knepley @*/ 1784b02e2d75SMatthew G Knepley PetscErrorCode PCFieldSplitGetType(PC pc, PCCompositeType *type) 1785b02e2d75SMatthew G Knepley { 1786b02e2d75SMatthew G Knepley PC_FieldSplit *jac = (PC_FieldSplit*) pc->data; 1787b02e2d75SMatthew G Knepley 1788b02e2d75SMatthew G Knepley PetscFunctionBegin; 1789b02e2d75SMatthew G Knepley PetscValidHeaderSpecific(pc,PC_CLASSID,1); 1790b02e2d75SMatthew G Knepley PetscValidIntPointer(type,2); 1791b02e2d75SMatthew G Knepley *type = jac->type; 1792b02e2d75SMatthew G Knepley PetscFunctionReturn(0); 1793b02e2d75SMatthew G Knepley } 1794b02e2d75SMatthew G Knepley 17954ab8060aSDmitry Karpeev #undef __FUNCT__ 17964ab8060aSDmitry Karpeev #define __FUNCT__ "PCFieldSplitSetDMSplits" 17974ab8060aSDmitry Karpeev /*@ 17984ab8060aSDmitry Karpeev PCFieldSplitSetDMSplits - Flags whether DMCreateFieldDecomposition() should be used to define the splits, whenever possible. 17994ab8060aSDmitry Karpeev 18004ab8060aSDmitry Karpeev Logically Collective 18014ab8060aSDmitry Karpeev 18024ab8060aSDmitry Karpeev Input Parameters: 18034ab8060aSDmitry Karpeev + pc - the preconditioner context 18044ab8060aSDmitry Karpeev - flg - boolean indicating whether to use field splits defined by the DM 18054ab8060aSDmitry Karpeev 18064ab8060aSDmitry Karpeev Options Database Key: 18074ab8060aSDmitry Karpeev . -pc_fieldsplit_dm_splits 18084ab8060aSDmitry Karpeev 18094ab8060aSDmitry Karpeev Level: Intermediate 18104ab8060aSDmitry Karpeev 18114ab8060aSDmitry Karpeev .keywords: PC, DM, composite preconditioner, additive, multiplicative 18124ab8060aSDmitry Karpeev 18134ab8060aSDmitry Karpeev .seealso: PCFieldSplitGetDMSplits() 18144ab8060aSDmitry Karpeev 18154ab8060aSDmitry Karpeev @*/ 18164ab8060aSDmitry Karpeev PetscErrorCode PCFieldSplitSetDMSplits(PC pc,PetscBool flg) 18174ab8060aSDmitry Karpeev { 18184ab8060aSDmitry Karpeev PC_FieldSplit *jac = (PC_FieldSplit*)pc->data; 18194ab8060aSDmitry Karpeev PetscBool isfs; 18204ab8060aSDmitry Karpeev PetscErrorCode ierr; 18214ab8060aSDmitry Karpeev 18224ab8060aSDmitry Karpeev PetscFunctionBegin; 18234ab8060aSDmitry Karpeev PetscValidHeaderSpecific(pc,PC_CLASSID,1); 18244ab8060aSDmitry Karpeev PetscValidLogicalCollectiveBool(pc,flg,2); 18254ab8060aSDmitry Karpeev ierr = PetscObjectTypeCompare((PetscObject)pc,PCFIELDSPLIT,&isfs);CHKERRQ(ierr); 18264ab8060aSDmitry Karpeev if (isfs) { 18274ab8060aSDmitry Karpeev jac->dm_splits = flg; 18284ab8060aSDmitry Karpeev } 18294ab8060aSDmitry Karpeev PetscFunctionReturn(0); 18304ab8060aSDmitry Karpeev } 18314ab8060aSDmitry Karpeev 18324ab8060aSDmitry Karpeev 18334ab8060aSDmitry Karpeev #undef __FUNCT__ 18344ab8060aSDmitry Karpeev #define __FUNCT__ "PCFieldSplitGetDMSplits" 18354ab8060aSDmitry Karpeev /*@ 18364ab8060aSDmitry Karpeev PCFieldSplitGetDMSplits - Returns flag indicating whether DMCreateFieldDecomposition() should be used to define the splits, whenever possible. 18374ab8060aSDmitry Karpeev 18384ab8060aSDmitry Karpeev Logically Collective 18394ab8060aSDmitry Karpeev 18404ab8060aSDmitry Karpeev Input Parameter: 18414ab8060aSDmitry Karpeev . pc - the preconditioner context 18424ab8060aSDmitry Karpeev 18434ab8060aSDmitry Karpeev Output Parameter: 18444ab8060aSDmitry Karpeev . flg - boolean indicating whether to use field splits defined by the DM 18454ab8060aSDmitry Karpeev 18464ab8060aSDmitry Karpeev Level: Intermediate 18474ab8060aSDmitry Karpeev 18484ab8060aSDmitry Karpeev .keywords: PC, DM, composite preconditioner, additive, multiplicative 18494ab8060aSDmitry Karpeev 18504ab8060aSDmitry Karpeev .seealso: PCFieldSplitSetDMSplits() 18514ab8060aSDmitry Karpeev 18524ab8060aSDmitry Karpeev @*/ 18534ab8060aSDmitry Karpeev PetscErrorCode PCFieldSplitGetDMSplits(PC pc,PetscBool* flg) 18544ab8060aSDmitry Karpeev { 18554ab8060aSDmitry Karpeev PC_FieldSplit *jac = (PC_FieldSplit*)pc->data; 18564ab8060aSDmitry Karpeev PetscBool isfs; 18574ab8060aSDmitry Karpeev PetscErrorCode ierr; 18584ab8060aSDmitry Karpeev 18594ab8060aSDmitry Karpeev PetscFunctionBegin; 18604ab8060aSDmitry Karpeev PetscValidHeaderSpecific(pc,PC_CLASSID,1); 18614ab8060aSDmitry Karpeev PetscValidPointer(flg,2); 18624ab8060aSDmitry Karpeev ierr = PetscObjectTypeCompare((PetscObject)pc,PCFIELDSPLIT,&isfs);CHKERRQ(ierr); 18634ab8060aSDmitry Karpeev if (isfs) { 18644ab8060aSDmitry Karpeev if(flg) *flg = jac->dm_splits; 18654ab8060aSDmitry Karpeev } 18664ab8060aSDmitry Karpeev PetscFunctionReturn(0); 18674ab8060aSDmitry Karpeev } 18684ab8060aSDmitry Karpeev 18690971522cSBarry Smith /* -------------------------------------------------------------------------------------*/ 18700971522cSBarry Smith /*MC 1871a8c7a070SBarry Smith PCFIELDSPLIT - Preconditioner created by combining separate preconditioners for individual 1872a04f6461SBarry Smith fields or groups of fields. See the users manual section "Solving Block Matrices" for more details. 18730971522cSBarry Smith 1874edf189efSBarry Smith To set options on the solvers for each block append -fieldsplit_ to all the PC 1875edf189efSBarry Smith options database keys. For example, -fieldsplit_pc_type ilu -fieldsplit_pc_factor_levels 1 18760971522cSBarry Smith 1877a8c7a070SBarry Smith To set the options on the solvers separate for each block call PCFieldSplitGetSubKSP() 187869a612a9SBarry Smith and set the options directly on the resulting KSP object 18790971522cSBarry Smith 18800971522cSBarry Smith Level: intermediate 18810971522cSBarry Smith 188279416396SBarry Smith Options Database Keys: 188381540f2fSBarry Smith + -pc_fieldsplit_%d_fields <a,b,..> - indicates the fields to be used in the %d'th split 188481540f2fSBarry Smith . -pc_fieldsplit_default - automatically add any fields to additional splits that have not 188581540f2fSBarry Smith been supplied explicitly by -pc_fieldsplit_%d_fields 188681540f2fSBarry Smith . -pc_fieldsplit_block_size <bs> - size of block that defines fields (i.e. there are bs fields) 18870f188ba9SJed Brown . -pc_fieldsplit_type <additive,multiplicative,symmetric_multiplicative,schur> - type of relaxation or factorization splitting 1888a7476a74SDmitry Karpeev . -pc_fieldsplit_schur_precondition <self,selfp,user,a11> - default is a11 1889435f959eSBarry Smith . -pc_fieldsplit_detect_saddle_point - automatically finds rows with zero or negative diagonal and uses Schur complement with no preconditioner as the solver 189079416396SBarry Smith 18915d4c12cdSJungho Lee - Options prefix for inner solvers when using Schur complement preconditioner are -fieldsplit_0_ and -fieldsplit_1_ 18925d4c12cdSJungho Lee for all other solvers they are -fieldsplit_%d_ for the dth field, use -fieldsplit_ for all fields 18935d4c12cdSJungho Lee 1894c8a0d604SMatthew G Knepley Notes: 1895c8a0d604SMatthew G Knepley Use PCFieldSplitSetFields() to set fields defined by "strided" entries and PCFieldSplitSetIS() 1896d32f9abdSBarry Smith to define a field by an arbitrary collection of entries. 1897d32f9abdSBarry Smith 1898d32f9abdSBarry Smith If no fields are set the default is used. The fields are defined by entries strided by bs, 1899d32f9abdSBarry Smith beginning at 0 then 1, etc to bs-1. The block size can be set with PCFieldSplitSetBlockSize(), 1900d32f9abdSBarry Smith if this is not called the block size defaults to the blocksize of the second matrix passed 1901d32f9abdSBarry Smith to KSPSetOperators()/PCSetOperators(). 1902d32f9abdSBarry Smith 1903c8a0d604SMatthew G Knepley $ For the Schur complement preconditioner if J = ( A00 A01 ) 1904c8a0d604SMatthew G Knepley $ ( A10 A11 ) 1905c8a0d604SMatthew G Knepley $ the preconditioner using full factorization is 1906c8a0d604SMatthew G Knepley $ ( I -A10 ksp(A00) ) ( inv(A00) 0 ) ( I 0 ) 1907c8a0d604SMatthew G Knepley $ ( 0 I ) ( 0 ksp(S) ) ( -A10 ksp(A00) I ) 1908a04f6461SBarry Smith where the action of inv(A00) is applied using the KSP solver with prefix -fieldsplit_0_. The action of 1909c8a0d604SMatthew G Knepley ksp(S) is computed using the KSP solver with prefix -fieldsplit_splitname_ (where splitname was given 1910a7476a74SDmitry Karpeev in providing the SECOND split or 1 if not given). For PCFieldSplitGetKSP() when field number is 0, 1911c8a0d604SMatthew G Knepley it returns the KSP associated with -fieldsplit_0_ while field number 1 gives -fieldsplit_1_ KSP. By default 1912a04f6461SBarry Smith A11 is used to construct a preconditioner for S, use PCFieldSplitSchurPrecondition() to turn on or off this 1913a7476a74SDmitry Karpeev option. You can use the preconditioner PCLSC to precondition the Schur complement with -fieldsplit_1_pc_type lsc. 1914a7476a74SDmitry Karpeev When option -fieldsplit_schur_precondition selfp is given, an approximation to S is assembled -- 1915a7476a74SDmitry Karpeev Sp = A11 - A10 inv(diag(A00)) A01, which has type AIJ and can be used with a variety of preconditioners 1916a7476a74SDmitry Karpeev (e.g., -fieldsplit_1_pc_type asm). 1917a7476a74SDmitry Karpeev The factorization type is set using -pc_fieldsplit_schur_fact_type <diag, lower, upper, full>. The full is shown above, 19185668aaf4SBarry Smith diag gives 1919c8a0d604SMatthew G Knepley $ ( inv(A00) 0 ) 1920c8a0d604SMatthew G Knepley $ ( 0 -ksp(S) ) 19215668aaf4SBarry Smith note that slightly counter intuitively there is a negative in front of the ksp(S) so that the preconditioner is positive definite. The lower factorization is the inverse of 1922c8a0d604SMatthew G Knepley $ ( A00 0 ) 1923c8a0d604SMatthew G Knepley $ ( A10 S ) 1924c8a0d604SMatthew G Knepley where the inverses of A00 and S are applied using KSPs. The upper factorization is the inverse of 1925c8a0d604SMatthew G Knepley $ ( A00 A01 ) 1926c8a0d604SMatthew G Knepley $ ( 0 S ) 1927c8a0d604SMatthew G Knepley where again the inverses of A00 and S are applied using KSPs. 1928e69d4d44SBarry Smith 1929edf189efSBarry Smith If only one set of indices (one IS) is provided with PCFieldSplitSetIS() then the complement of that IS 1930edf189efSBarry Smith is used automatically for a second block. 1931edf189efSBarry Smith 1932ff218e97SBarry Smith The fieldsplit preconditioner cannot currently be used with the BAIJ or SBAIJ data formats if the blocksize is larger than 1. 1933ff218e97SBarry Smith Generally it should be used with the AIJ format. 1934ff218e97SBarry Smith 1935ff218e97SBarry Smith The forms of these preconditioners are closely related if not identical to forms derived as "Distributive Iterations", see, 1936ff218e97SBarry Smith for example, page 294 in "Principles of Computational Fluid Dynamics" by Pieter Wesseling. Note that one can also use PCFIELDSPLIT 1937ff218e97SBarry Smith inside a smoother resulting in "Distributive Smoothers". 19380716a85fSBarry Smith 1939a541d17aSBarry Smith Concepts: physics based preconditioners, block preconditioners 19400971522cSBarry Smith 19417e8cb189SBarry Smith .seealso: PCCreate(), PCSetType(), PCType (for list of available types), PC, Block_Preconditioners, PCLSC, 1942e69d4d44SBarry Smith PCFieldSplitGetSubKSP(), PCFieldSplitSetFields(), PCFieldSplitSetType(), PCFieldSplitSetIS(), PCFieldSplitSchurPrecondition() 19430971522cSBarry Smith M*/ 19440971522cSBarry Smith 19450971522cSBarry Smith #undef __FUNCT__ 19460971522cSBarry Smith #define __FUNCT__ "PCCreate_FieldSplit" 19478cc058d9SJed Brown PETSC_EXTERN PetscErrorCode PCCreate_FieldSplit(PC pc) 19480971522cSBarry Smith { 19490971522cSBarry Smith PetscErrorCode ierr; 19500971522cSBarry Smith PC_FieldSplit *jac; 19510971522cSBarry Smith 19520971522cSBarry Smith PetscFunctionBegin; 1953b00a9115SJed Brown ierr = PetscNewLog(pc,&jac);CHKERRQ(ierr); 19542fa5cd67SKarl Rupp 19550971522cSBarry Smith jac->bs = -1; 19560971522cSBarry Smith jac->nsplits = 0; 19573e197d65SBarry Smith jac->type = PC_COMPOSITE_MULTIPLICATIVE; 1958e6cab6aaSJed Brown jac->schurpre = PC_FIELDSPLIT_SCHUR_PRE_USER; /* Try user preconditioner first, fall back on diagonal */ 1959c9c6ffaaSJed Brown jac->schurfactorization = PC_FIELDSPLIT_SCHUR_FACT_FULL; 1960fbe7908bSJed Brown jac->dm_splits = PETSC_TRUE; 196151f519a2SBarry Smith 19620971522cSBarry Smith pc->data = (void*)jac; 19630971522cSBarry Smith 19640971522cSBarry Smith pc->ops->apply = PCApply_FieldSplit; 1965421e10b8SBarry Smith pc->ops->applytranspose = PCApplyTranspose_FieldSplit; 19660971522cSBarry Smith pc->ops->setup = PCSetUp_FieldSplit; 1967574deadeSBarry Smith pc->ops->reset = PCReset_FieldSplit; 19680971522cSBarry Smith pc->ops->destroy = PCDestroy_FieldSplit; 19690971522cSBarry Smith pc->ops->setfromoptions = PCSetFromOptions_FieldSplit; 19700971522cSBarry Smith pc->ops->view = PCView_FieldSplit; 19710971522cSBarry Smith pc->ops->applyrichardson = 0; 19720971522cSBarry Smith 1973bdf89e91SBarry Smith ierr = PetscObjectComposeFunction((PetscObject)pc,"PCFieldSplitGetSubKSP_C",PCFieldSplitGetSubKSP_FieldSplit);CHKERRQ(ierr); 1974bdf89e91SBarry Smith ierr = PetscObjectComposeFunction((PetscObject)pc,"PCFieldSplitSetFields_C",PCFieldSplitSetFields_FieldSplit);CHKERRQ(ierr); 1975bdf89e91SBarry Smith ierr = PetscObjectComposeFunction((PetscObject)pc,"PCFieldSplitSetIS_C",PCFieldSplitSetIS_FieldSplit);CHKERRQ(ierr); 1976bdf89e91SBarry Smith ierr = PetscObjectComposeFunction((PetscObject)pc,"PCFieldSplitSetType_C",PCFieldSplitSetType_FieldSplit);CHKERRQ(ierr); 1977bdf89e91SBarry Smith ierr = PetscObjectComposeFunction((PetscObject)pc,"PCFieldSplitSetBlockSize_C",PCFieldSplitSetBlockSize_FieldSplit);CHKERRQ(ierr); 19780971522cSBarry Smith PetscFunctionReturn(0); 19790971522cSBarry Smith } 19800971522cSBarry Smith 19810971522cSBarry Smith 1982a541d17aSBarry Smith 1983