1 2 #include <petsc-private/pcimpl.h> /*I "petscpc.h" I*/ 3 #include <petscdm.h> 4 5 /* 6 There is a nice discussion of block preconditioners in 7 8 [El08] A taxonomy and comparison of parallel block multi-level preconditioners for the incompressible Navier-Stokes equations 9 Howard Elman, V.E. Howle, John Shadid, Robert Shuttleworth, Ray Tuminaro, Journal of Computational Physics 227 (2008) 1790--1808 10 http://chess.cs.umd.edu/~elman/papers/tax.pdf 11 */ 12 13 const char *const PCFieldSplitSchurPreTypes[] = {"SELF","A11","USER","PCFieldSplitSchurPreType","PC_FIELDSPLIT_SCHUR_PRE_",0}; 14 const char *const PCFieldSplitSchurFactTypes[] = {"DIAG","LOWER","UPPER","FULL","PCFieldSplitSchurFactType","PC_FIELDSPLIT_SCHUR_FACT_",0}; 15 16 typedef struct _PC_FieldSplitLink *PC_FieldSplitLink; 17 struct _PC_FieldSplitLink { 18 KSP ksp; 19 Vec x,y,z; 20 char *splitname; 21 PetscInt nfields; 22 PetscInt *fields,*fields_col; 23 VecScatter sctx; 24 IS is,is_col; 25 PC_FieldSplitLink next,previous; 26 }; 27 28 typedef struct { 29 PCCompositeType type; 30 PetscBool defaultsplit; /* Flag for a system with a set of 'k' scalar fields with the same layout (and bs = k) */ 31 PetscBool splitdefined; /* Flag is set after the splits have been defined, to prevent more splits from being added */ 32 PetscInt bs; /* Block size for IS and Mat structures */ 33 PetscInt nsplits; /* Number of field divisions defined */ 34 Vec *x,*y,w1,w2; 35 Mat *mat; /* The diagonal block for each split */ 36 Mat *pmat; /* The preconditioning diagonal block for each split */ 37 Mat *Afield; /* The rows of the matrix associated with each split */ 38 PetscBool issetup; 39 40 /* Only used when Schur complement preconditioning is used */ 41 Mat B; /* The (0,1) block */ 42 Mat C; /* The (1,0) block */ 43 Mat schur; /* The Schur complement S = A11 - A10 A00^{-1} A01, the KSP here, kspinner, is H_1 in [El08] */ 44 Mat schur_user; /* User-provided preconditioning matrix for the Schur complement */ 45 PCFieldSplitSchurPreType schurpre; /* Determines which preconditioning matrix is used for the Schur complement */ 46 PCFieldSplitSchurFactType schurfactorization; 47 KSP kspschur; /* The solver for S */ 48 KSP kspupper; /* The solver for A in the upper diagonal part of the factorization (H_2 in [El08]) */ 49 PC_FieldSplitLink head; 50 PetscBool reset; /* indicates PCReset() has been last called on this object, hack */ 51 PetscBool suboptionsset; /* Indicates that the KSPSetFromOptions() has been called on the sub-KSPs */ 52 PetscBool dm_splits; /* Whether to use DMCreateFieldDecomposition() whenever possible */ 53 } PC_FieldSplit; 54 55 /* 56 Notes: there is no particular reason that pmat, x, and y are stored as arrays in PC_FieldSplit instead of 57 inside PC_FieldSplitLink, just historical. If you want to be able to add new fields after already using the 58 PC you could change this. 59 */ 60 61 /* This helper is so that setting a user-provided preconditioning matrix is orthogonal to choosing to use it. This way the 62 * application-provided FormJacobian can provide this matrix without interfering with the user's (command-line) choices. */ 63 static Mat FieldSplitSchurPre(PC_FieldSplit *jac) 64 { 65 switch (jac->schurpre) { 66 case PC_FIELDSPLIT_SCHUR_PRE_SELF: return jac->schur; 67 case PC_FIELDSPLIT_SCHUR_PRE_A11: return jac->pmat[1]; 68 case PC_FIELDSPLIT_SCHUR_PRE_USER: /* Use a user-provided matrix if it is given, otherwise diagonal block */ 69 default: 70 return jac->schur_user ? jac->schur_user : jac->pmat[1]; 71 } 72 } 73 74 75 #include <petscdraw.h> 76 #undef __FUNCT__ 77 #define __FUNCT__ "PCView_FieldSplit" 78 static PetscErrorCode PCView_FieldSplit(PC pc,PetscViewer viewer) 79 { 80 PC_FieldSplit *jac = (PC_FieldSplit*)pc->data; 81 PetscErrorCode ierr; 82 PetscBool iascii,isdraw; 83 PetscInt i,j; 84 PC_FieldSplitLink ilink = jac->head; 85 86 PetscFunctionBegin; 87 ierr = PetscObjectTypeCompare((PetscObject)viewer,PETSCVIEWERASCII,&iascii);CHKERRQ(ierr); 88 ierr = PetscObjectTypeCompare((PetscObject)viewer,PETSCVIEWERDRAW,&isdraw);CHKERRQ(ierr); 89 if (iascii) { 90 if (jac->bs > 0) { 91 ierr = PetscViewerASCIIPrintf(viewer," FieldSplit with %s composition: total splits = %D, blocksize = %D\n",PCCompositeTypes[jac->type],jac->nsplits,jac->bs);CHKERRQ(ierr); 92 } else { 93 ierr = PetscViewerASCIIPrintf(viewer," FieldSplit with %s composition: total splits = %D\n",PCCompositeTypes[jac->type],jac->nsplits);CHKERRQ(ierr); 94 } 95 if (pc->useAmat) { 96 ierr = PetscViewerASCIIPrintf(viewer," using Amat (not Pmat) as operator for blocks\n");CHKERRQ(ierr); 97 } 98 ierr = PetscViewerASCIIPrintf(viewer," Solver info for each split is in the following KSP objects:\n");CHKERRQ(ierr); 99 ierr = PetscViewerASCIIPushTab(viewer);CHKERRQ(ierr); 100 for (i=0; i<jac->nsplits; i++) { 101 if (ilink->fields) { 102 ierr = PetscViewerASCIIPrintf(viewer,"Split number %D Fields ",i);CHKERRQ(ierr); 103 ierr = PetscViewerASCIIUseTabs(viewer,PETSC_FALSE);CHKERRQ(ierr); 104 for (j=0; j<ilink->nfields; j++) { 105 if (j > 0) { 106 ierr = PetscViewerASCIIPrintf(viewer,",");CHKERRQ(ierr); 107 } 108 ierr = PetscViewerASCIIPrintf(viewer," %D",ilink->fields[j]);CHKERRQ(ierr); 109 } 110 ierr = PetscViewerASCIIPrintf(viewer,"\n");CHKERRQ(ierr); 111 ierr = PetscViewerASCIIUseTabs(viewer,PETSC_TRUE);CHKERRQ(ierr); 112 } else { 113 ierr = PetscViewerASCIIPrintf(viewer,"Split number %D Defined by IS\n",i);CHKERRQ(ierr); 114 } 115 ierr = KSPView(ilink->ksp,viewer);CHKERRQ(ierr); 116 ilink = ilink->next; 117 } 118 ierr = PetscViewerASCIIPopTab(viewer);CHKERRQ(ierr); 119 } 120 121 if (isdraw) { 122 PetscDraw draw; 123 PetscReal x,y,w,wd; 124 125 ierr = PetscViewerDrawGetDraw(viewer,0,&draw);CHKERRQ(ierr); 126 ierr = PetscDrawGetCurrentPoint(draw,&x,&y);CHKERRQ(ierr); 127 w = 2*PetscMin(1.0 - x,x); 128 wd = w/(jac->nsplits + 1); 129 x = x - wd*(jac->nsplits-1)/2.0; 130 for (i=0; i<jac->nsplits; i++) { 131 ierr = PetscDrawPushCurrentPoint(draw,x,y);CHKERRQ(ierr); 132 ierr = KSPView(ilink->ksp,viewer);CHKERRQ(ierr); 133 ierr = PetscDrawPopCurrentPoint(draw);CHKERRQ(ierr); 134 x += wd; 135 ilink = ilink->next; 136 } 137 } 138 PetscFunctionReturn(0); 139 } 140 141 #undef __FUNCT__ 142 #define __FUNCT__ "PCView_FieldSplit_Schur" 143 static PetscErrorCode PCView_FieldSplit_Schur(PC pc,PetscViewer viewer) 144 { 145 PC_FieldSplit *jac = (PC_FieldSplit*)pc->data; 146 PetscErrorCode ierr; 147 PetscBool iascii,isdraw; 148 PetscInt i,j; 149 PC_FieldSplitLink ilink = jac->head; 150 151 PetscFunctionBegin; 152 ierr = PetscObjectTypeCompare((PetscObject)viewer,PETSCVIEWERASCII,&iascii);CHKERRQ(ierr); 153 ierr = PetscObjectTypeCompare((PetscObject)viewer,PETSCVIEWERDRAW,&isdraw);CHKERRQ(ierr); 154 if (iascii) { 155 if (jac->bs > 0) { 156 ierr = PetscViewerASCIIPrintf(viewer," FieldSplit with Schur preconditioner, blocksize = %D, factorization %s\n",jac->bs,PCFieldSplitSchurFactTypes[jac->schurfactorization]);CHKERRQ(ierr); 157 } else { 158 ierr = PetscViewerASCIIPrintf(viewer," FieldSplit with Schur preconditioner, factorization %s\n",PCFieldSplitSchurFactTypes[jac->schurfactorization]);CHKERRQ(ierr); 159 } 160 if (pc->useAmat) { 161 ierr = PetscViewerASCIIPrintf(viewer," using Amat (not Pmat) as operator for blocks\n");CHKERRQ(ierr); 162 } 163 switch (jac->schurpre) { 164 case PC_FIELDSPLIT_SCHUR_PRE_SELF: 165 ierr = PetscViewerASCIIPrintf(viewer," Preconditioner for the Schur complement formed from S itself\n");CHKERRQ(ierr);break; 166 case PC_FIELDSPLIT_SCHUR_PRE_A11: 167 ierr = PetscViewerASCIIPrintf(viewer," Preconditioner for the Schur complement formed from A11\n");CHKERRQ(ierr);break; 168 case PC_FIELDSPLIT_SCHUR_PRE_USER: 169 if (jac->schur_user) { 170 ierr = PetscViewerASCIIPrintf(viewer," Preconditioner for the Schur complement formed from user provided matrix\n");CHKERRQ(ierr); 171 } else { 172 ierr = PetscViewerASCIIPrintf(viewer," Preconditioner for the Schur complement formed from A11\n");CHKERRQ(ierr); 173 } 174 break; 175 default: 176 SETERRQ1(PetscObjectComm((PetscObject)pc), PETSC_ERR_ARG_OUTOFRANGE, "Invalid Schur preconditioning type: %d", jac->schurpre); 177 } 178 ierr = PetscViewerASCIIPrintf(viewer," Split info:\n");CHKERRQ(ierr); 179 ierr = PetscViewerASCIIPushTab(viewer);CHKERRQ(ierr); 180 for (i=0; i<jac->nsplits; i++) { 181 if (ilink->fields) { 182 ierr = PetscViewerASCIIPrintf(viewer,"Split number %D Fields ",i);CHKERRQ(ierr); 183 ierr = PetscViewerASCIIUseTabs(viewer,PETSC_FALSE);CHKERRQ(ierr); 184 for (j=0; j<ilink->nfields; j++) { 185 if (j > 0) { 186 ierr = PetscViewerASCIIPrintf(viewer,",");CHKERRQ(ierr); 187 } 188 ierr = PetscViewerASCIIPrintf(viewer," %D",ilink->fields[j]);CHKERRQ(ierr); 189 } 190 ierr = PetscViewerASCIIPrintf(viewer,"\n");CHKERRQ(ierr); 191 ierr = PetscViewerASCIIUseTabs(viewer,PETSC_TRUE);CHKERRQ(ierr); 192 } else { 193 ierr = PetscViewerASCIIPrintf(viewer,"Split number %D Defined by IS\n",i);CHKERRQ(ierr); 194 } 195 ilink = ilink->next; 196 } 197 ierr = PetscViewerASCIIPrintf(viewer,"KSP solver for A00 block \n");CHKERRQ(ierr); 198 ierr = PetscViewerASCIIPushTab(viewer);CHKERRQ(ierr); 199 ierr = KSPView(jac->head->ksp,viewer);CHKERRQ(ierr); 200 ierr = PetscViewerASCIIPopTab(viewer);CHKERRQ(ierr); 201 if (jac->kspupper != jac->head->ksp) { 202 ierr = PetscViewerASCIIPrintf(viewer,"KSP solver for upper A00 in upper triangular factor \n");CHKERRQ(ierr); 203 ierr = PetscViewerASCIIPushTab(viewer);CHKERRQ(ierr); 204 if (jac->kspupper) {ierr = KSPView(jac->kspupper,viewer);CHKERRQ(ierr);} 205 else {ierr = PetscViewerASCIIPrintf(viewer," not yet available\n");CHKERRQ(ierr);} 206 ierr = PetscViewerASCIIPopTab(viewer);CHKERRQ(ierr); 207 } 208 ierr = PetscViewerASCIIPrintf(viewer,"KSP solver for S = A11 - A10 inv(A00) A01 \n");CHKERRQ(ierr); 209 ierr = PetscViewerASCIIPushTab(viewer);CHKERRQ(ierr); 210 if (jac->kspschur) { 211 ierr = KSPView(jac->kspschur,viewer);CHKERRQ(ierr); 212 } else { 213 ierr = PetscViewerASCIIPrintf(viewer," not yet available\n");CHKERRQ(ierr); 214 } 215 ierr = PetscViewerASCIIPopTab(viewer);CHKERRQ(ierr); 216 ierr = PetscViewerASCIIPopTab(viewer);CHKERRQ(ierr); 217 } else if (isdraw) { 218 PetscDraw draw; 219 PetscReal x,y,w,wd,h; 220 PetscInt cnt = 2; 221 char str[32]; 222 223 ierr = PetscViewerDrawGetDraw(viewer,0,&draw);CHKERRQ(ierr); 224 ierr = PetscDrawGetCurrentPoint(draw,&x,&y);CHKERRQ(ierr); 225 if (jac->kspupper != jac->head->ksp) cnt++; 226 w = 2*PetscMin(1.0 - x,x); 227 wd = w/(cnt + 1); 228 229 ierr = PetscSNPrintf(str,32,"Schur fact. %s",PCFieldSplitSchurFactTypes[jac->schurfactorization]);CHKERRQ(ierr); 230 ierr = PetscDrawBoxedString(draw,x,y,PETSC_DRAW_RED,PETSC_DRAW_BLACK,str,NULL,&h);CHKERRQ(ierr); 231 y -= h; 232 if (jac->schurpre == PC_FIELDSPLIT_SCHUR_PRE_USER && !jac->schur_user) { 233 ierr = PetscSNPrintf(str,32,"Prec. for Schur from %s",PCFieldSplitSchurPreTypes[PC_FIELDSPLIT_SCHUR_PRE_A11]);CHKERRQ(ierr); 234 } else { 235 ierr = PetscSNPrintf(str,32,"Prec. for Schur from %s",PCFieldSplitSchurPreTypes[jac->schurpre]);CHKERRQ(ierr); 236 } 237 ierr = PetscDrawBoxedString(draw,x+wd*(cnt-1)/2.0,y,PETSC_DRAW_RED,PETSC_DRAW_BLACK,str,NULL,&h);CHKERRQ(ierr); 238 y -= h; 239 x = x - wd*(cnt-1)/2.0; 240 241 ierr = PetscDrawPushCurrentPoint(draw,x,y);CHKERRQ(ierr); 242 ierr = KSPView(jac->head->ksp,viewer);CHKERRQ(ierr); 243 ierr = PetscDrawPopCurrentPoint(draw);CHKERRQ(ierr); 244 if (jac->kspupper != jac->head->ksp) { 245 x += wd; 246 ierr = PetscDrawPushCurrentPoint(draw,x,y);CHKERRQ(ierr); 247 ierr = KSPView(jac->kspupper,viewer);CHKERRQ(ierr); 248 ierr = PetscDrawPopCurrentPoint(draw);CHKERRQ(ierr); 249 } 250 x += wd; 251 ierr = PetscDrawPushCurrentPoint(draw,x,y);CHKERRQ(ierr); 252 ierr = KSPView(jac->kspschur,viewer);CHKERRQ(ierr); 253 ierr = PetscDrawPopCurrentPoint(draw);CHKERRQ(ierr); 254 } 255 PetscFunctionReturn(0); 256 } 257 258 #undef __FUNCT__ 259 #define __FUNCT__ "PCFieldSplitSetRuntimeSplits_Private" 260 /* Precondition: jac->bs is set to a meaningful value */ 261 static PetscErrorCode PCFieldSplitSetRuntimeSplits_Private(PC pc) 262 { 263 PetscErrorCode ierr; 264 PC_FieldSplit *jac = (PC_FieldSplit*)pc->data; 265 PetscInt i,nfields,*ifields,nfields_col,*ifields_col; 266 PetscBool flg,flg_col; 267 char optionname[128],splitname[8],optionname_col[128]; 268 269 PetscFunctionBegin; 270 ierr = PetscMalloc1(jac->bs,&ifields);CHKERRQ(ierr); 271 ierr = PetscMalloc1(jac->bs,&ifields_col);CHKERRQ(ierr); 272 for (i=0,flg=PETSC_TRUE;; i++) { 273 ierr = PetscSNPrintf(splitname,sizeof(splitname),"%D",i);CHKERRQ(ierr); 274 ierr = PetscSNPrintf(optionname,sizeof(optionname),"-pc_fieldsplit_%D_fields",i);CHKERRQ(ierr); 275 ierr = PetscSNPrintf(optionname_col,sizeof(optionname_col),"-pc_fieldsplit_%D_fields_col",i);CHKERRQ(ierr); 276 nfields = jac->bs; 277 nfields_col = jac->bs; 278 ierr = PetscOptionsGetIntArray(((PetscObject)pc)->prefix,optionname,ifields,&nfields,&flg);CHKERRQ(ierr); 279 ierr = PetscOptionsGetIntArray(((PetscObject)pc)->prefix,optionname_col,ifields_col,&nfields_col,&flg_col);CHKERRQ(ierr); 280 if (!flg) break; 281 else if (flg && !flg_col) { 282 if (!nfields) SETERRQ(PETSC_COMM_SELF,PETSC_ERR_USER,"Cannot list zero fields"); 283 ierr = PCFieldSplitSetFields(pc,splitname,nfields,ifields,ifields);CHKERRQ(ierr); 284 } else { 285 if (!nfields || !nfields_col) SETERRQ(PETSC_COMM_SELF,PETSC_ERR_USER,"Cannot list zero fields"); 286 if (nfields != nfields_col) SETERRQ(PETSC_COMM_SELF,PETSC_ERR_USER,"Number of row and column fields must match"); 287 ierr = PCFieldSplitSetFields(pc,splitname,nfields,ifields,ifields_col);CHKERRQ(ierr); 288 } 289 } 290 if (i > 0) { 291 /* Makes command-line setting of splits take precedence over setting them in code. 292 Otherwise subsequent calls to PCFieldSplitSetIS() or PCFieldSplitSetFields() would 293 create new splits, which would probably not be what the user wanted. */ 294 jac->splitdefined = PETSC_TRUE; 295 } 296 ierr = PetscFree(ifields);CHKERRQ(ierr); 297 ierr = PetscFree(ifields_col);CHKERRQ(ierr); 298 PetscFunctionReturn(0); 299 } 300 301 #undef __FUNCT__ 302 #define __FUNCT__ "PCFieldSplitSetDefaults" 303 static PetscErrorCode PCFieldSplitSetDefaults(PC pc) 304 { 305 PC_FieldSplit *jac = (PC_FieldSplit*)pc->data; 306 PetscErrorCode ierr; 307 PC_FieldSplitLink ilink = jac->head; 308 PetscBool fieldsplit_default = PETSC_FALSE,stokes = PETSC_FALSE; 309 PetscInt i; 310 311 PetscFunctionBegin; 312 /* 313 Kinda messy, but at least this now uses DMCreateFieldDecomposition() even with jac->reset. 314 Should probably be rewritten. 315 */ 316 if (!ilink || jac->reset) { 317 ierr = PetscOptionsGetBool(((PetscObject)pc)->prefix,"-pc_fieldsplit_detect_saddle_point",&stokes,NULL);CHKERRQ(ierr); 318 if (pc->dm && jac->dm_splits && !stokes) { 319 PetscInt numFields, f, i, j; 320 char **fieldNames; 321 IS *fields; 322 DM *dms; 323 DM subdm[128]; 324 PetscBool flg; 325 326 ierr = DMCreateFieldDecomposition(pc->dm, &numFields, &fieldNames, &fields, &dms);CHKERRQ(ierr); 327 /* Allow the user to prescribe the splits */ 328 for (i = 0, flg = PETSC_TRUE;; i++) { 329 PetscInt ifields[128]; 330 IS compField; 331 char optionname[128], splitname[8]; 332 PetscInt nfields = numFields; 333 334 ierr = PetscSNPrintf(optionname, sizeof(optionname), "-pc_fieldsplit_%D_fields", i);CHKERRQ(ierr); 335 ierr = PetscOptionsGetIntArray(((PetscObject) pc)->prefix, optionname, ifields, &nfields, &flg);CHKERRQ(ierr); 336 if (!flg) break; 337 if (numFields > 128) SETERRQ1(PetscObjectComm((PetscObject)pc),PETSC_ERR_SUP,"Cannot currently support %d > 128 fields", numFields); 338 ierr = DMCreateSubDM(pc->dm, nfields, ifields, &compField, &subdm[i]);CHKERRQ(ierr); 339 if (nfields == 1) { 340 ierr = PCFieldSplitSetIS(pc, fieldNames[ifields[0]], compField);CHKERRQ(ierr); 341 /* ierr = PetscPrintf(PetscObjectComm((PetscObject)pc), "%s Field Indices:", fieldNames[ifields[0]]);CHKERRQ(ierr); 342 ierr = ISView(compField, NULL);CHKERRQ(ierr); */ 343 } else { 344 ierr = PetscSNPrintf(splitname, sizeof(splitname), "%D", i);CHKERRQ(ierr); 345 ierr = PCFieldSplitSetIS(pc, splitname, compField);CHKERRQ(ierr); 346 /* ierr = PetscPrintf(PetscObjectComm((PetscObject)pc), "%s Field Indices:", splitname);CHKERRQ(ierr); 347 ierr = ISView(compField, NULL);CHKERRQ(ierr); */ 348 } 349 ierr = ISDestroy(&compField);CHKERRQ(ierr); 350 for (j = 0; j < nfields; ++j) { 351 f = ifields[j]; 352 ierr = PetscFree(fieldNames[f]);CHKERRQ(ierr); 353 ierr = ISDestroy(&fields[f]);CHKERRQ(ierr); 354 } 355 } 356 if (i == 0) { 357 for (f = 0; f < numFields; ++f) { 358 ierr = PCFieldSplitSetIS(pc, fieldNames[f], fields[f]);CHKERRQ(ierr); 359 ierr = PetscFree(fieldNames[f]);CHKERRQ(ierr); 360 ierr = ISDestroy(&fields[f]);CHKERRQ(ierr); 361 } 362 } else { 363 for (j=0; j<numFields; j++) { 364 ierr = DMDestroy(dms+j);CHKERRQ(ierr); 365 } 366 ierr = PetscFree(dms);CHKERRQ(ierr); 367 ierr = PetscMalloc1(i, &dms);CHKERRQ(ierr); 368 for (j = 0; j < i; ++j) dms[j] = subdm[j]; 369 } 370 ierr = PetscFree(fieldNames);CHKERRQ(ierr); 371 ierr = PetscFree(fields);CHKERRQ(ierr); 372 if (dms) { 373 ierr = PetscInfo(pc, "Setting up physics based fieldsplit preconditioner using the embedded DM\n");CHKERRQ(ierr); 374 for (ilink = jac->head, i = 0; ilink; ilink = ilink->next, ++i) { 375 const char *prefix; 376 ierr = PetscObjectGetOptionsPrefix((PetscObject)(ilink->ksp),&prefix);CHKERRQ(ierr); 377 ierr = PetscObjectSetOptionsPrefix((PetscObject)(dms[i]), prefix);CHKERRQ(ierr); 378 ierr = KSPSetDM(ilink->ksp, dms[i]);CHKERRQ(ierr); 379 ierr = KSPSetDMActive(ilink->ksp, PETSC_FALSE);CHKERRQ(ierr); 380 ierr = PetscObjectIncrementTabLevel((PetscObject)dms[i],(PetscObject)ilink->ksp,0);CHKERRQ(ierr); 381 ierr = DMDestroy(&dms[i]);CHKERRQ(ierr); 382 } 383 ierr = PetscFree(dms);CHKERRQ(ierr); 384 } 385 } else { 386 if (jac->bs <= 0) { 387 if (pc->pmat) { 388 ierr = MatGetBlockSize(pc->pmat,&jac->bs);CHKERRQ(ierr); 389 } else jac->bs = 1; 390 } 391 392 if (stokes) { 393 IS zerodiags,rest; 394 PetscInt nmin,nmax; 395 396 ierr = MatGetOwnershipRange(pc->mat,&nmin,&nmax);CHKERRQ(ierr); 397 ierr = MatFindZeroDiagonals(pc->mat,&zerodiags);CHKERRQ(ierr); 398 ierr = ISComplement(zerodiags,nmin,nmax,&rest);CHKERRQ(ierr); 399 if (jac->reset) { 400 jac->head->is = rest; 401 jac->head->next->is = zerodiags; 402 } else { 403 ierr = PCFieldSplitSetIS(pc,"0",rest);CHKERRQ(ierr); 404 ierr = PCFieldSplitSetIS(pc,"1",zerodiags);CHKERRQ(ierr); 405 } 406 ierr = ISDestroy(&zerodiags);CHKERRQ(ierr); 407 ierr = ISDestroy(&rest);CHKERRQ(ierr); 408 } else { 409 if (jac->reset) SETERRQ(PetscObjectComm((PetscObject)pc),PETSC_ERR_SUP,"Cases not yet handled when PCReset() was used"); 410 ierr = PetscOptionsGetBool(((PetscObject)pc)->prefix,"-pc_fieldsplit_default",&fieldsplit_default,NULL);CHKERRQ(ierr); 411 if (!fieldsplit_default) { 412 /* Allow user to set fields from command line, if bs was known at the time of PCSetFromOptions_FieldSplit() 413 then it is set there. This is not ideal because we should only have options set in XXSetFromOptions(). */ 414 ierr = PCFieldSplitSetRuntimeSplits_Private(pc);CHKERRQ(ierr); 415 if (jac->splitdefined) {ierr = PetscInfo(pc,"Splits defined using the options database\n");CHKERRQ(ierr);} 416 } 417 if (fieldsplit_default || !jac->splitdefined) { 418 ierr = PetscInfo(pc,"Using default splitting of fields\n");CHKERRQ(ierr); 419 for (i=0; i<jac->bs; i++) { 420 char splitname[8]; 421 ierr = PetscSNPrintf(splitname,sizeof(splitname),"%D",i);CHKERRQ(ierr); 422 ierr = PCFieldSplitSetFields(pc,splitname,1,&i,&i);CHKERRQ(ierr); 423 } 424 jac->defaultsplit = PETSC_TRUE; 425 } 426 } 427 } 428 } else if (jac->nsplits == 1) { 429 if (ilink->is) { 430 IS is2; 431 PetscInt nmin,nmax; 432 433 ierr = MatGetOwnershipRange(pc->mat,&nmin,&nmax);CHKERRQ(ierr); 434 ierr = ISComplement(ilink->is,nmin,nmax,&is2);CHKERRQ(ierr); 435 ierr = PCFieldSplitSetIS(pc,"1",is2);CHKERRQ(ierr); 436 ierr = ISDestroy(&is2);CHKERRQ(ierr); 437 } else SETERRQ(PetscObjectComm((PetscObject)pc),PETSC_ERR_SUP,"Must provide at least two sets of fields to PCFieldSplit()"); 438 } 439 440 441 if (jac->nsplits < 2) SETERRQ1(PetscObjectComm((PetscObject)pc),PETSC_ERR_PLIB,"Unhandled case, must have at least two fields, not %d", jac->nsplits); 442 PetscFunctionReturn(0); 443 } 444 445 PETSC_EXTERN PetscErrorCode PetscOptionsFindPairPrefix_Private(const char pre[], const char name[], char *value[], PetscBool *flg); 446 447 #undef __FUNCT__ 448 #define __FUNCT__ "PCSetUp_FieldSplit" 449 static PetscErrorCode PCSetUp_FieldSplit(PC pc) 450 { 451 PC_FieldSplit *jac = (PC_FieldSplit*)pc->data; 452 PetscErrorCode ierr; 453 PC_FieldSplitLink ilink; 454 PetscInt i,nsplit; 455 MatStructure flag = pc->flag; 456 PetscBool sorted, sorted_col; 457 458 PetscFunctionBegin; 459 ierr = PCFieldSplitSetDefaults(pc);CHKERRQ(ierr); 460 nsplit = jac->nsplits; 461 ilink = jac->head; 462 463 /* get the matrices for each split */ 464 if (!jac->issetup) { 465 PetscInt rstart,rend,nslots,bs; 466 467 jac->issetup = PETSC_TRUE; 468 469 /* This is done here instead of in PCFieldSplitSetFields() because may not have matrix at that point */ 470 if (jac->defaultsplit || !ilink->is) { 471 if (jac->bs <= 0) jac->bs = nsplit; 472 } 473 bs = jac->bs; 474 ierr = MatGetOwnershipRange(pc->pmat,&rstart,&rend);CHKERRQ(ierr); 475 nslots = (rend - rstart)/bs; 476 for (i=0; i<nsplit; i++) { 477 if (jac->defaultsplit) { 478 ierr = ISCreateStride(PetscObjectComm((PetscObject)pc),nslots,rstart+i,nsplit,&ilink->is);CHKERRQ(ierr); 479 ierr = ISDuplicate(ilink->is,&ilink->is_col);CHKERRQ(ierr); 480 } else if (!ilink->is) { 481 if (ilink->nfields > 1) { 482 PetscInt *ii,*jj,j,k,nfields = ilink->nfields,*fields = ilink->fields,*fields_col = ilink->fields_col; 483 ierr = PetscMalloc1(ilink->nfields*nslots,&ii);CHKERRQ(ierr); 484 ierr = PetscMalloc1(ilink->nfields*nslots,&jj);CHKERRQ(ierr); 485 for (j=0; j<nslots; j++) { 486 for (k=0; k<nfields; k++) { 487 ii[nfields*j + k] = rstart + bs*j + fields[k]; 488 jj[nfields*j + k] = rstart + bs*j + fields_col[k]; 489 } 490 } 491 ierr = ISCreateGeneral(PetscObjectComm((PetscObject)pc),nslots*nfields,ii,PETSC_OWN_POINTER,&ilink->is);CHKERRQ(ierr); 492 ierr = ISCreateGeneral(PetscObjectComm((PetscObject)pc),nslots*nfields,jj,PETSC_OWN_POINTER,&ilink->is_col);CHKERRQ(ierr); 493 } else { 494 ierr = ISCreateStride(PetscObjectComm((PetscObject)pc),nslots,rstart+ilink->fields[0],bs,&ilink->is);CHKERRQ(ierr); 495 ierr = ISCreateStride(PetscObjectComm((PetscObject)pc),nslots,rstart+ilink->fields_col[0],bs,&ilink->is_col);CHKERRQ(ierr); 496 } 497 } 498 ierr = ISSorted(ilink->is,&sorted);CHKERRQ(ierr); 499 if (ilink->is_col) { ierr = ISSorted(ilink->is_col,&sorted_col);CHKERRQ(ierr); } 500 if (!sorted || !sorted_col) SETERRQ(PETSC_COMM_SELF,PETSC_ERR_USER,"Fields must be sorted when creating split"); 501 ilink = ilink->next; 502 } 503 } 504 505 ilink = jac->head; 506 if (!jac->pmat) { 507 Vec xtmp; 508 509 ierr = MatGetVecs(pc->pmat,&xtmp,NULL);CHKERRQ(ierr); 510 ierr = PetscMalloc1(nsplit,&jac->pmat);CHKERRQ(ierr); 511 ierr = PetscMalloc2(nsplit,&jac->x,nsplit,&jac->y);CHKERRQ(ierr); 512 for (i=0; i<nsplit; i++) { 513 MatNullSpace sp; 514 515 /* Check for preconditioning matrix attached to IS */ 516 ierr = PetscObjectQuery((PetscObject) ilink->is, "pmat", (PetscObject*) &jac->pmat[i]);CHKERRQ(ierr); 517 if (jac->pmat[i]) { 518 ierr = PetscObjectReference((PetscObject) jac->pmat[i]);CHKERRQ(ierr); 519 if (jac->type == PC_COMPOSITE_SCHUR) { 520 jac->schur_user = jac->pmat[i]; 521 522 ierr = PetscObjectReference((PetscObject) jac->schur_user);CHKERRQ(ierr); 523 } 524 } else { 525 ierr = MatGetSubMatrix(pc->pmat,ilink->is,ilink->is_col,MAT_INITIAL_MATRIX,&jac->pmat[i]);CHKERRQ(ierr); 526 } 527 /* create work vectors for each split */ 528 ierr = MatGetVecs(jac->pmat[i],&jac->x[i],&jac->y[i]);CHKERRQ(ierr); 529 ilink->x = jac->x[i]; ilink->y = jac->y[i]; ilink->z = NULL; 530 /* compute scatter contexts needed by multiplicative versions and non-default splits */ 531 ierr = VecScatterCreate(xtmp,ilink->is,jac->x[i],NULL,&ilink->sctx);CHKERRQ(ierr); 532 /* Check for null space attached to IS */ 533 ierr = PetscObjectQuery((PetscObject) ilink->is, "nullspace", (PetscObject*) &sp);CHKERRQ(ierr); 534 if (sp) { 535 ierr = MatSetNullSpace(jac->pmat[i], sp);CHKERRQ(ierr); 536 } 537 ierr = PetscObjectQuery((PetscObject) ilink->is, "nearnullspace", (PetscObject*) &sp);CHKERRQ(ierr); 538 if (sp) { 539 ierr = MatSetNearNullSpace(jac->pmat[i], sp);CHKERRQ(ierr); 540 } 541 ilink = ilink->next; 542 } 543 ierr = VecDestroy(&xtmp);CHKERRQ(ierr); 544 } else { 545 for (i=0; i<nsplit; i++) { 546 Mat pmat; 547 548 /* Check for preconditioning matrix attached to IS */ 549 ierr = PetscObjectQuery((PetscObject) ilink->is, "pmat", (PetscObject*) &pmat);CHKERRQ(ierr); 550 if (!pmat) { 551 ierr = MatGetSubMatrix(pc->pmat,ilink->is,ilink->is_col,MAT_REUSE_MATRIX,&jac->pmat[i]);CHKERRQ(ierr); 552 } 553 ilink = ilink->next; 554 } 555 } 556 if (pc->useAmat) { 557 ilink = jac->head; 558 if (!jac->mat) { 559 ierr = PetscMalloc1(nsplit,&jac->mat);CHKERRQ(ierr); 560 for (i=0; i<nsplit; i++) { 561 ierr = MatGetSubMatrix(pc->mat,ilink->is,ilink->is_col,MAT_INITIAL_MATRIX,&jac->mat[i]);CHKERRQ(ierr); 562 ilink = ilink->next; 563 } 564 } else { 565 for (i=0; i<nsplit; i++) { 566 if (jac->mat[i]) {ierr = MatGetSubMatrix(pc->mat,ilink->is,ilink->is_col,MAT_REUSE_MATRIX,&jac->mat[i]);CHKERRQ(ierr);} 567 ilink = ilink->next; 568 } 569 } 570 } else { 571 jac->mat = jac->pmat; 572 } 573 574 if (jac->type != PC_COMPOSITE_ADDITIVE && jac->type != PC_COMPOSITE_SCHUR) { 575 /* extract the rows of the matrix associated with each field: used for efficient computation of residual inside algorithm */ 576 ilink = jac->head; 577 if (!jac->Afield) { 578 ierr = PetscMalloc1(nsplit,&jac->Afield);CHKERRQ(ierr); 579 for (i=0; i<nsplit; i++) { 580 ierr = MatGetSubMatrix(pc->mat,ilink->is,NULL,MAT_INITIAL_MATRIX,&jac->Afield[i]);CHKERRQ(ierr); 581 ilink = ilink->next; 582 } 583 } else { 584 for (i=0; i<nsplit; i++) { 585 ierr = MatGetSubMatrix(pc->mat,ilink->is,NULL,MAT_REUSE_MATRIX,&jac->Afield[i]);CHKERRQ(ierr); 586 ilink = ilink->next; 587 } 588 } 589 } 590 591 if (jac->type == PC_COMPOSITE_SCHUR) { 592 IS ccis; 593 PetscInt rstart,rend; 594 char lscname[256]; 595 PetscObject LSC_L; 596 597 if (nsplit != 2) SETERRQ(PetscObjectComm((PetscObject)pc),PETSC_ERR_ARG_INCOMP,"To use Schur complement preconditioner you must have exactly 2 fields"); 598 599 /* When extracting off-diagonal submatrices, we take complements from this range */ 600 ierr = MatGetOwnershipRangeColumn(pc->mat,&rstart,&rend);CHKERRQ(ierr); 601 602 /* need to handle case when one is resetting up the preconditioner */ 603 if (jac->schur) { 604 KSP kspA = jac->head->ksp, kspInner = NULL, kspUpper = jac->kspupper; 605 606 ierr = MatSchurComplementGetKSP(jac->schur, &kspInner);CHKERRQ(ierr); 607 ilink = jac->head; 608 ierr = ISComplement(ilink->is_col,rstart,rend,&ccis);CHKERRQ(ierr); 609 ierr = MatGetSubMatrix(pc->mat,ilink->is,ccis,MAT_REUSE_MATRIX,&jac->B);CHKERRQ(ierr); 610 ierr = ISDestroy(&ccis);CHKERRQ(ierr); 611 ilink = ilink->next; 612 ierr = ISComplement(ilink->is_col,rstart,rend,&ccis);CHKERRQ(ierr); 613 ierr = MatGetSubMatrix(pc->mat,ilink->is,ccis,MAT_REUSE_MATRIX,&jac->C);CHKERRQ(ierr); 614 ierr = ISDestroy(&ccis);CHKERRQ(ierr); 615 ierr = MatSchurComplementUpdate(jac->schur,jac->mat[0],jac->pmat[0],jac->B,jac->C,jac->mat[1],pc->flag);CHKERRQ(ierr); 616 if (kspA != kspInner) { 617 ierr = KSPSetOperators(kspA,jac->mat[0],jac->pmat[0],pc->flag);CHKERRQ(ierr); 618 } 619 if (kspUpper != kspA) { 620 ierr = KSPSetOperators(kspUpper,jac->mat[0],jac->pmat[0],pc->flag);CHKERRQ(ierr); 621 } 622 ierr = KSPSetOperators(jac->kspschur,jac->schur,FieldSplitSchurPre(jac),pc->flag);CHKERRQ(ierr); 623 } else { 624 const char *Dprefix; 625 char schurprefix[256]; 626 char schurtestoption[256]; 627 MatNullSpace sp; 628 PetscBool flg; 629 630 /* extract the A01 and A10 matrices */ 631 ilink = jac->head; 632 ierr = ISComplement(ilink->is_col,rstart,rend,&ccis);CHKERRQ(ierr); 633 ierr = MatGetSubMatrix(pc->mat,ilink->is,ccis,MAT_INITIAL_MATRIX,&jac->B);CHKERRQ(ierr); 634 ierr = ISDestroy(&ccis);CHKERRQ(ierr); 635 ilink = ilink->next; 636 ierr = ISComplement(ilink->is_col,rstart,rend,&ccis);CHKERRQ(ierr); 637 ierr = MatGetSubMatrix(pc->mat,ilink->is,ccis,MAT_INITIAL_MATRIX,&jac->C);CHKERRQ(ierr); 638 ierr = ISDestroy(&ccis);CHKERRQ(ierr); 639 640 /* Use mat[0] (diagonal block of Amat) preconditioned by pmat[0] to define Schur complement */ 641 ierr = MatCreate(((PetscObject)jac->mat[0])->comm,&jac->schur);CHKERRQ(ierr); 642 ierr = MatSetType(jac->schur,MATSCHURCOMPLEMENT);CHKERRQ(ierr); 643 ierr = MatSchurComplementSet(jac->schur,jac->mat[0],jac->pmat[0],jac->B,jac->C,jac->mat[1]);CHKERRQ(ierr); 644 645 ierr = MatGetNullSpace(jac->pmat[1], &sp);CHKERRQ(ierr); 646 if (sp) { 647 ierr = MatSetNullSpace(jac->schur, sp);CHKERRQ(ierr); 648 } 649 650 ierr = PetscSNPrintf(schurtestoption, sizeof(schurtestoption), "-fieldsplit_%s_inner_", ilink->splitname);CHKERRQ(ierr); 651 ierr = PetscOptionsFindPairPrefix_Private(((PetscObject)pc)->prefix, schurtestoption, NULL, &flg);CHKERRQ(ierr); 652 if (flg) { 653 DM dmInner; 654 KSP kspInner; 655 656 ierr = MatSchurComplementGetKSP(jac->schur, &kspInner);CHKERRQ(ierr); 657 ierr = PetscSNPrintf(schurprefix, sizeof(schurprefix), "%sfieldsplit_%s_inner_", ((PetscObject)pc)->prefix ? ((PetscObject)pc)->prefix : "", ilink->splitname);CHKERRQ(ierr); 658 /* Indent this deeper to emphasize the "inner" nature of this solver. */ 659 ierr = PetscObjectIncrementTabLevel((PetscObject)kspInner, (PetscObject) pc, 2);CHKERRQ(ierr); 660 ierr = KSPSetOptionsPrefix(kspInner, schurprefix);CHKERRQ(ierr); 661 662 /* Set DM for new solver */ 663 ierr = KSPGetDM(jac->head->ksp, &dmInner);CHKERRQ(ierr); 664 ierr = KSPSetDM(kspInner, dmInner);CHKERRQ(ierr); 665 ierr = KSPSetDMActive(kspInner, PETSC_FALSE);CHKERRQ(ierr); 666 } else { 667 /* Use the outer solver for the inner solve, but revert the KSPPREONLY from PCFieldSplitSetFields_FieldSplit or 668 * PCFieldSplitSetIS_FieldSplit. We don't want KSPPREONLY because it makes the Schur complement inexact, 669 * preventing Schur complement reduction to be an accurate solve. Usually when an iterative solver is used for 670 * S = D - C A_inner^{-1} B, we expect S to be defined using an accurate definition of A_inner^{-1}, so we make 671 * GMRES the default. Note that it is also common to use PREONLY for S, in which case S may not be used 672 * directly, and the user is responsible for setting an inexact method for fieldsplit's A^{-1}. */ 673 ierr = KSPSetType(jac->head->ksp,KSPGMRES);CHKERRQ(ierr); 674 ierr = MatSchurComplementSetKSP(jac->schur,jac->head->ksp);CHKERRQ(ierr); 675 } 676 ierr = KSPSetOperators(jac->head->ksp,jac->mat[0],jac->pmat[0],flag);CHKERRQ(ierr); 677 ierr = KSPSetFromOptions(jac->head->ksp);CHKERRQ(ierr); 678 ierr = MatSetFromOptions(jac->schur);CHKERRQ(ierr); 679 680 ierr = PetscSNPrintf(schurtestoption, sizeof(schurtestoption), "-fieldsplit_%s_upper_", ilink->splitname);CHKERRQ(ierr); 681 ierr = PetscOptionsFindPairPrefix_Private(((PetscObject)pc)->prefix, schurtestoption, NULL, &flg);CHKERRQ(ierr); 682 if (flg) { 683 DM dmInner; 684 685 ierr = PetscSNPrintf(schurprefix, sizeof(schurprefix), "%sfieldsplit_%s_upper_", ((PetscObject)pc)->prefix ? ((PetscObject)pc)->prefix : "", ilink->splitname);CHKERRQ(ierr); 686 ierr = KSPCreate(PetscObjectComm((PetscObject)pc), &jac->kspupper);CHKERRQ(ierr); 687 ierr = KSPSetOptionsPrefix(jac->kspupper, schurprefix);CHKERRQ(ierr); 688 ierr = KSPGetDM(jac->head->ksp, &dmInner);CHKERRQ(ierr); 689 ierr = KSPSetDM(jac->kspupper, dmInner);CHKERRQ(ierr); 690 ierr = KSPSetDMActive(jac->kspupper, PETSC_FALSE);CHKERRQ(ierr); 691 ierr = KSPSetFromOptions(jac->kspupper);CHKERRQ(ierr); 692 ierr = KSPSetOperators(jac->kspupper,jac->mat[0],jac->pmat[0],flag);CHKERRQ(ierr); 693 ierr = VecDuplicate(jac->head->x, &jac->head->z);CHKERRQ(ierr); 694 } else { 695 jac->kspupper = jac->head->ksp; 696 ierr = PetscObjectReference((PetscObject) jac->head->ksp);CHKERRQ(ierr); 697 } 698 699 ierr = KSPCreate(PetscObjectComm((PetscObject)pc),&jac->kspschur);CHKERRQ(ierr); 700 ierr = PetscLogObjectParent((PetscObject)pc,(PetscObject)jac->kspschur);CHKERRQ(ierr); 701 ierr = PetscObjectIncrementTabLevel((PetscObject)jac->kspschur,(PetscObject)pc,1);CHKERRQ(ierr); 702 ierr = KSPSetOperators(jac->kspschur,jac->schur,FieldSplitSchurPre(jac),DIFFERENT_NONZERO_PATTERN);CHKERRQ(ierr); 703 if (jac->schurpre == PC_FIELDSPLIT_SCHUR_PRE_SELF) { 704 PC pcschur; 705 ierr = KSPGetPC(jac->kspschur,&pcschur);CHKERRQ(ierr); 706 ierr = PCSetType(pcschur,PCNONE);CHKERRQ(ierr); 707 /* Note: This is bad if there exist preconditioners for MATSCHURCOMPLEMENT */ 708 } 709 ierr = KSPGetOptionsPrefix(jac->head->next->ksp, &Dprefix);CHKERRQ(ierr); 710 ierr = KSPSetOptionsPrefix(jac->kspschur, Dprefix);CHKERRQ(ierr); 711 /* propogate DM */ 712 { 713 DM sdm; 714 ierr = KSPGetDM(jac->head->next->ksp, &sdm);CHKERRQ(ierr); 715 if (sdm) { 716 ierr = KSPSetDM(jac->kspschur, sdm);CHKERRQ(ierr); 717 ierr = KSPSetDMActive(jac->kspschur, PETSC_FALSE);CHKERRQ(ierr); 718 } 719 } 720 /* really want setfromoptions called in PCSetFromOptions_FieldSplit(), but it is not ready yet */ 721 /* need to call this every time, since the jac->kspschur is freshly created, otherwise its options never get set */ 722 ierr = KSPSetFromOptions(jac->kspschur);CHKERRQ(ierr); 723 } 724 725 /* HACK: special support to forward L and Lp matrices that might be used by PCLSC */ 726 ierr = PetscSNPrintf(lscname,sizeof(lscname),"%s_LSC_L",ilink->splitname);CHKERRQ(ierr); 727 ierr = PetscObjectQuery((PetscObject)pc->mat,lscname,(PetscObject*)&LSC_L);CHKERRQ(ierr); 728 if (!LSC_L) {ierr = PetscObjectQuery((PetscObject)pc->pmat,lscname,(PetscObject*)&LSC_L);CHKERRQ(ierr);} 729 if (LSC_L) {ierr = PetscObjectCompose((PetscObject)jac->schur,"LSC_L",(PetscObject)LSC_L);CHKERRQ(ierr);} 730 ierr = PetscSNPrintf(lscname,sizeof(lscname),"%s_LSC_Lp",ilink->splitname);CHKERRQ(ierr); 731 ierr = PetscObjectQuery((PetscObject)pc->pmat,lscname,(PetscObject*)&LSC_L);CHKERRQ(ierr); 732 if (!LSC_L) {ierr = PetscObjectQuery((PetscObject)pc->mat,lscname,(PetscObject*)&LSC_L);CHKERRQ(ierr);} 733 if (LSC_L) {ierr = PetscObjectCompose((PetscObject)jac->schur,"LSC_Lp",(PetscObject)LSC_L);CHKERRQ(ierr);} 734 } else { 735 /* set up the individual splits' PCs */ 736 i = 0; 737 ilink = jac->head; 738 while (ilink) { 739 ierr = KSPSetOperators(ilink->ksp,jac->mat[i],jac->pmat[i],flag);CHKERRQ(ierr); 740 /* really want setfromoptions called in PCSetFromOptions_FieldSplit(), but it is not ready yet */ 741 if (!jac->suboptionsset) {ierr = KSPSetFromOptions(ilink->ksp);CHKERRQ(ierr);} 742 i++; 743 ilink = ilink->next; 744 } 745 } 746 747 jac->suboptionsset = PETSC_TRUE; 748 PetscFunctionReturn(0); 749 } 750 751 #define FieldSplitSplitSolveAdd(ilink,xx,yy) \ 752 (VecScatterBegin(ilink->sctx,xx,ilink->x,INSERT_VALUES,SCATTER_FORWARD) || \ 753 VecScatterEnd(ilink->sctx,xx,ilink->x,INSERT_VALUES,SCATTER_FORWARD) || \ 754 KSPSolve(ilink->ksp,ilink->x,ilink->y) || \ 755 VecScatterBegin(ilink->sctx,ilink->y,yy,ADD_VALUES,SCATTER_REVERSE) || \ 756 VecScatterEnd(ilink->sctx,ilink->y,yy,ADD_VALUES,SCATTER_REVERSE)) 757 758 #undef __FUNCT__ 759 #define __FUNCT__ "PCApply_FieldSplit_Schur" 760 static PetscErrorCode PCApply_FieldSplit_Schur(PC pc,Vec x,Vec y) 761 { 762 PC_FieldSplit *jac = (PC_FieldSplit*)pc->data; 763 PetscErrorCode ierr; 764 PC_FieldSplitLink ilinkA = jac->head, ilinkD = ilinkA->next; 765 KSP kspA = ilinkA->ksp, kspLower = kspA, kspUpper = jac->kspupper; 766 767 PetscFunctionBegin; 768 switch (jac->schurfactorization) { 769 case PC_FIELDSPLIT_SCHUR_FACT_DIAG: 770 /* [A00 0; 0 -S], positive definite, suitable for MINRES */ 771 ierr = VecScatterBegin(ilinkA->sctx,x,ilinkA->x,INSERT_VALUES,SCATTER_FORWARD);CHKERRQ(ierr); 772 ierr = VecScatterBegin(ilinkD->sctx,x,ilinkD->x,INSERT_VALUES,SCATTER_FORWARD);CHKERRQ(ierr); 773 ierr = VecScatterEnd(ilinkA->sctx,x,ilinkA->x,INSERT_VALUES,SCATTER_FORWARD);CHKERRQ(ierr); 774 ierr = KSPSolve(kspA,ilinkA->x,ilinkA->y);CHKERRQ(ierr); 775 ierr = VecScatterBegin(ilinkA->sctx,ilinkA->y,y,INSERT_VALUES,SCATTER_REVERSE);CHKERRQ(ierr); 776 ierr = VecScatterEnd(ilinkD->sctx,x,ilinkD->x,INSERT_VALUES,SCATTER_FORWARD);CHKERRQ(ierr); 777 ierr = KSPSolve(jac->kspschur,ilinkD->x,ilinkD->y);CHKERRQ(ierr); 778 ierr = VecScale(ilinkD->y,-1.);CHKERRQ(ierr); 779 ierr = VecScatterBegin(ilinkD->sctx,ilinkD->y,y,INSERT_VALUES,SCATTER_REVERSE);CHKERRQ(ierr); 780 ierr = VecScatterEnd(ilinkA->sctx,ilinkA->y,y,INSERT_VALUES,SCATTER_REVERSE);CHKERRQ(ierr); 781 ierr = VecScatterEnd(ilinkD->sctx,ilinkD->y,y,INSERT_VALUES,SCATTER_REVERSE);CHKERRQ(ierr); 782 break; 783 case PC_FIELDSPLIT_SCHUR_FACT_LOWER: 784 /* [A00 0; A10 S], suitable for left preconditioning */ 785 ierr = VecScatterBegin(ilinkA->sctx,x,ilinkA->x,INSERT_VALUES,SCATTER_FORWARD);CHKERRQ(ierr); 786 ierr = VecScatterEnd(ilinkA->sctx,x,ilinkA->x,INSERT_VALUES,SCATTER_FORWARD);CHKERRQ(ierr); 787 ierr = KSPSolve(kspA,ilinkA->x,ilinkA->y);CHKERRQ(ierr); 788 ierr = MatMult(jac->C,ilinkA->y,ilinkD->x);CHKERRQ(ierr); 789 ierr = VecScale(ilinkD->x,-1.);CHKERRQ(ierr); 790 ierr = VecScatterBegin(ilinkD->sctx,x,ilinkD->x,ADD_VALUES,SCATTER_FORWARD);CHKERRQ(ierr); 791 ierr = VecScatterBegin(ilinkA->sctx,ilinkA->y,y,INSERT_VALUES,SCATTER_REVERSE);CHKERRQ(ierr); 792 ierr = VecScatterEnd(ilinkD->sctx,x,ilinkD->x,ADD_VALUES,SCATTER_FORWARD);CHKERRQ(ierr); 793 ierr = KSPSolve(jac->kspschur,ilinkD->x,ilinkD->y);CHKERRQ(ierr); 794 ierr = VecScatterBegin(ilinkD->sctx,ilinkD->y,y,INSERT_VALUES,SCATTER_REVERSE);CHKERRQ(ierr); 795 ierr = VecScatterEnd(ilinkA->sctx,ilinkA->y,y,INSERT_VALUES,SCATTER_REVERSE);CHKERRQ(ierr); 796 ierr = VecScatterEnd(ilinkD->sctx,ilinkD->y,y,INSERT_VALUES,SCATTER_REVERSE);CHKERRQ(ierr); 797 break; 798 case PC_FIELDSPLIT_SCHUR_FACT_UPPER: 799 /* [A00 A01; 0 S], suitable for right preconditioning */ 800 ierr = VecScatterBegin(ilinkD->sctx,x,ilinkD->x,INSERT_VALUES,SCATTER_FORWARD);CHKERRQ(ierr); 801 ierr = VecScatterEnd(ilinkD->sctx,x,ilinkD->x,INSERT_VALUES,SCATTER_FORWARD);CHKERRQ(ierr); 802 ierr = KSPSolve(jac->kspschur,ilinkD->x,ilinkD->y);CHKERRQ(ierr); 803 ierr = MatMult(jac->B,ilinkD->y,ilinkA->x);CHKERRQ(ierr); 804 ierr = VecScale(ilinkA->x,-1.);CHKERRQ(ierr); 805 ierr = VecScatterBegin(ilinkA->sctx,x,ilinkA->x,ADD_VALUES,SCATTER_FORWARD);CHKERRQ(ierr); 806 ierr = VecScatterBegin(ilinkD->sctx,ilinkD->y,y,INSERT_VALUES,SCATTER_REVERSE);CHKERRQ(ierr); 807 ierr = VecScatterEnd(ilinkA->sctx,x,ilinkA->x,ADD_VALUES,SCATTER_FORWARD);CHKERRQ(ierr); 808 ierr = KSPSolve(kspA,ilinkA->x,ilinkA->y);CHKERRQ(ierr); 809 ierr = VecScatterBegin(ilinkA->sctx,ilinkA->y,y,INSERT_VALUES,SCATTER_REVERSE);CHKERRQ(ierr); 810 ierr = VecScatterEnd(ilinkD->sctx,ilinkD->y,y,INSERT_VALUES,SCATTER_REVERSE);CHKERRQ(ierr); 811 ierr = VecScatterEnd(ilinkA->sctx,ilinkA->y,y,INSERT_VALUES,SCATTER_REVERSE);CHKERRQ(ierr); 812 break; 813 case PC_FIELDSPLIT_SCHUR_FACT_FULL: 814 /* [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 */ 815 ierr = VecScatterBegin(ilinkA->sctx,x,ilinkA->x,INSERT_VALUES,SCATTER_FORWARD);CHKERRQ(ierr); 816 ierr = VecScatterEnd(ilinkA->sctx,x,ilinkA->x,INSERT_VALUES,SCATTER_FORWARD);CHKERRQ(ierr); 817 ierr = KSPSolve(kspLower,ilinkA->x,ilinkA->y);CHKERRQ(ierr); 818 ierr = MatMult(jac->C,ilinkA->y,ilinkD->x);CHKERRQ(ierr); 819 ierr = VecScale(ilinkD->x,-1.0);CHKERRQ(ierr); 820 ierr = VecScatterBegin(ilinkD->sctx,x,ilinkD->x,ADD_VALUES,SCATTER_FORWARD);CHKERRQ(ierr); 821 ierr = VecScatterEnd(ilinkD->sctx,x,ilinkD->x,ADD_VALUES,SCATTER_FORWARD);CHKERRQ(ierr); 822 823 ierr = KSPSolve(jac->kspschur,ilinkD->x,ilinkD->y);CHKERRQ(ierr); 824 ierr = VecScatterBegin(ilinkD->sctx,ilinkD->y,y,INSERT_VALUES,SCATTER_REVERSE);CHKERRQ(ierr); 825 ierr = VecScatterEnd(ilinkD->sctx,ilinkD->y,y,INSERT_VALUES,SCATTER_REVERSE);CHKERRQ(ierr); 826 827 if (kspUpper == kspA) { 828 ierr = MatMult(jac->B,ilinkD->y,ilinkA->y);CHKERRQ(ierr); 829 ierr = VecAXPY(ilinkA->x,-1.0,ilinkA->y);CHKERRQ(ierr); 830 ierr = KSPSolve(kspA,ilinkA->x,ilinkA->y);CHKERRQ(ierr); 831 } else { 832 ierr = KSPSolve(kspA,ilinkA->x,ilinkA->y);CHKERRQ(ierr); 833 ierr = MatMult(jac->B,ilinkD->y,ilinkA->x);CHKERRQ(ierr); 834 ierr = KSPSolve(kspUpper,ilinkA->x,ilinkA->z);CHKERRQ(ierr); 835 ierr = VecAXPY(ilinkA->y,-1.0,ilinkA->z);CHKERRQ(ierr); 836 } 837 ierr = VecScatterBegin(ilinkA->sctx,ilinkA->y,y,INSERT_VALUES,SCATTER_REVERSE);CHKERRQ(ierr); 838 ierr = VecScatterEnd(ilinkA->sctx,ilinkA->y,y,INSERT_VALUES,SCATTER_REVERSE);CHKERRQ(ierr); 839 } 840 PetscFunctionReturn(0); 841 } 842 843 #undef __FUNCT__ 844 #define __FUNCT__ "PCApply_FieldSplit" 845 static PetscErrorCode PCApply_FieldSplit(PC pc,Vec x,Vec y) 846 { 847 PC_FieldSplit *jac = (PC_FieldSplit*)pc->data; 848 PetscErrorCode ierr; 849 PC_FieldSplitLink ilink = jac->head; 850 PetscInt cnt,bs; 851 852 PetscFunctionBegin; 853 if (jac->type == PC_COMPOSITE_ADDITIVE) { 854 if (jac->defaultsplit) { 855 ierr = VecGetBlockSize(x,&bs);CHKERRQ(ierr); 856 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); 857 ierr = VecGetBlockSize(y,&bs);CHKERRQ(ierr); 858 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); 859 ierr = VecStrideGatherAll(x,jac->x,INSERT_VALUES);CHKERRQ(ierr); 860 while (ilink) { 861 ierr = KSPSolve(ilink->ksp,ilink->x,ilink->y);CHKERRQ(ierr); 862 ilink = ilink->next; 863 } 864 ierr = VecStrideScatterAll(jac->y,y,INSERT_VALUES);CHKERRQ(ierr); 865 } else { 866 ierr = VecSet(y,0.0);CHKERRQ(ierr); 867 while (ilink) { 868 ierr = FieldSplitSplitSolveAdd(ilink,x,y);CHKERRQ(ierr); 869 ilink = ilink->next; 870 } 871 } 872 } else if (jac->type == PC_COMPOSITE_MULTIPLICATIVE || jac->type == PC_COMPOSITE_SYMMETRIC_MULTIPLICATIVE) { 873 if (!jac->w1) { 874 ierr = VecDuplicate(x,&jac->w1);CHKERRQ(ierr); 875 ierr = VecDuplicate(x,&jac->w2);CHKERRQ(ierr); 876 } 877 ierr = VecSet(y,0.0);CHKERRQ(ierr); 878 ierr = FieldSplitSplitSolveAdd(ilink,x,y);CHKERRQ(ierr); 879 cnt = 1; 880 while (ilink->next) { 881 ilink = ilink->next; 882 /* compute the residual only over the part of the vector needed */ 883 ierr = MatMult(jac->Afield[cnt++],y,ilink->x);CHKERRQ(ierr); 884 ierr = VecScale(ilink->x,-1.0);CHKERRQ(ierr); 885 ierr = VecScatterBegin(ilink->sctx,x,ilink->x,ADD_VALUES,SCATTER_FORWARD);CHKERRQ(ierr); 886 ierr = VecScatterEnd(ilink->sctx,x,ilink->x,ADD_VALUES,SCATTER_FORWARD);CHKERRQ(ierr); 887 ierr = KSPSolve(ilink->ksp,ilink->x,ilink->y);CHKERRQ(ierr); 888 ierr = VecScatterBegin(ilink->sctx,ilink->y,y,ADD_VALUES,SCATTER_REVERSE);CHKERRQ(ierr); 889 ierr = VecScatterEnd(ilink->sctx,ilink->y,y,ADD_VALUES,SCATTER_REVERSE);CHKERRQ(ierr); 890 } 891 if (jac->type == PC_COMPOSITE_SYMMETRIC_MULTIPLICATIVE) { 892 cnt -= 2; 893 while (ilink->previous) { 894 ilink = ilink->previous; 895 /* compute the residual only over the part of the vector needed */ 896 ierr = MatMult(jac->Afield[cnt--],y,ilink->x);CHKERRQ(ierr); 897 ierr = VecScale(ilink->x,-1.0);CHKERRQ(ierr); 898 ierr = VecScatterBegin(ilink->sctx,x,ilink->x,ADD_VALUES,SCATTER_FORWARD);CHKERRQ(ierr); 899 ierr = VecScatterEnd(ilink->sctx,x,ilink->x,ADD_VALUES,SCATTER_FORWARD);CHKERRQ(ierr); 900 ierr = KSPSolve(ilink->ksp,ilink->x,ilink->y);CHKERRQ(ierr); 901 ierr = VecScatterBegin(ilink->sctx,ilink->y,y,ADD_VALUES,SCATTER_REVERSE);CHKERRQ(ierr); 902 ierr = VecScatterEnd(ilink->sctx,ilink->y,y,ADD_VALUES,SCATTER_REVERSE);CHKERRQ(ierr); 903 } 904 } 905 } else SETERRQ1(PetscObjectComm((PetscObject)pc),PETSC_ERR_SUP,"Unsupported or unknown composition",(int) jac->type); 906 PetscFunctionReturn(0); 907 } 908 909 #define FieldSplitSplitSolveAddTranspose(ilink,xx,yy) \ 910 (VecScatterBegin(ilink->sctx,xx,ilink->y,INSERT_VALUES,SCATTER_FORWARD) || \ 911 VecScatterEnd(ilink->sctx,xx,ilink->y,INSERT_VALUES,SCATTER_FORWARD) || \ 912 KSPSolveTranspose(ilink->ksp,ilink->y,ilink->x) || \ 913 VecScatterBegin(ilink->sctx,ilink->x,yy,ADD_VALUES,SCATTER_REVERSE) || \ 914 VecScatterEnd(ilink->sctx,ilink->x,yy,ADD_VALUES,SCATTER_REVERSE)) 915 916 #undef __FUNCT__ 917 #define __FUNCT__ "PCApplyTranspose_FieldSplit" 918 static PetscErrorCode PCApplyTranspose_FieldSplit(PC pc,Vec x,Vec y) 919 { 920 PC_FieldSplit *jac = (PC_FieldSplit*)pc->data; 921 PetscErrorCode ierr; 922 PC_FieldSplitLink ilink = jac->head; 923 PetscInt bs; 924 925 PetscFunctionBegin; 926 if (jac->type == PC_COMPOSITE_ADDITIVE) { 927 if (jac->defaultsplit) { 928 ierr = VecGetBlockSize(x,&bs);CHKERRQ(ierr); 929 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); 930 ierr = VecGetBlockSize(y,&bs);CHKERRQ(ierr); 931 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); 932 ierr = VecStrideGatherAll(x,jac->x,INSERT_VALUES);CHKERRQ(ierr); 933 while (ilink) { 934 ierr = KSPSolveTranspose(ilink->ksp,ilink->x,ilink->y);CHKERRQ(ierr); 935 ilink = ilink->next; 936 } 937 ierr = VecStrideScatterAll(jac->y,y,INSERT_VALUES);CHKERRQ(ierr); 938 } else { 939 ierr = VecSet(y,0.0);CHKERRQ(ierr); 940 while (ilink) { 941 ierr = FieldSplitSplitSolveAddTranspose(ilink,x,y);CHKERRQ(ierr); 942 ilink = ilink->next; 943 } 944 } 945 } else { 946 if (!jac->w1) { 947 ierr = VecDuplicate(x,&jac->w1);CHKERRQ(ierr); 948 ierr = VecDuplicate(x,&jac->w2);CHKERRQ(ierr); 949 } 950 ierr = VecSet(y,0.0);CHKERRQ(ierr); 951 if (jac->type == PC_COMPOSITE_SYMMETRIC_MULTIPLICATIVE) { 952 ierr = FieldSplitSplitSolveAddTranspose(ilink,x,y);CHKERRQ(ierr); 953 while (ilink->next) { 954 ilink = ilink->next; 955 ierr = MatMultTranspose(pc->mat,y,jac->w1);CHKERRQ(ierr); 956 ierr = VecWAXPY(jac->w2,-1.0,jac->w1,x);CHKERRQ(ierr); 957 ierr = FieldSplitSplitSolveAddTranspose(ilink,jac->w2,y);CHKERRQ(ierr); 958 } 959 while (ilink->previous) { 960 ilink = ilink->previous; 961 ierr = MatMultTranspose(pc->mat,y,jac->w1);CHKERRQ(ierr); 962 ierr = VecWAXPY(jac->w2,-1.0,jac->w1,x);CHKERRQ(ierr); 963 ierr = FieldSplitSplitSolveAddTranspose(ilink,jac->w2,y);CHKERRQ(ierr); 964 } 965 } else { 966 while (ilink->next) { /* get to last entry in linked list */ 967 ilink = ilink->next; 968 } 969 ierr = FieldSplitSplitSolveAddTranspose(ilink,x,y);CHKERRQ(ierr); 970 while (ilink->previous) { 971 ilink = ilink->previous; 972 ierr = MatMultTranspose(pc->mat,y,jac->w1);CHKERRQ(ierr); 973 ierr = VecWAXPY(jac->w2,-1.0,jac->w1,x);CHKERRQ(ierr); 974 ierr = FieldSplitSplitSolveAddTranspose(ilink,jac->w2,y);CHKERRQ(ierr); 975 } 976 } 977 } 978 PetscFunctionReturn(0); 979 } 980 981 #undef __FUNCT__ 982 #define __FUNCT__ "PCReset_FieldSplit" 983 static PetscErrorCode PCReset_FieldSplit(PC pc) 984 { 985 PC_FieldSplit *jac = (PC_FieldSplit*)pc->data; 986 PetscErrorCode ierr; 987 PC_FieldSplitLink ilink = jac->head,next; 988 989 PetscFunctionBegin; 990 while (ilink) { 991 ierr = KSPReset(ilink->ksp);CHKERRQ(ierr); 992 ierr = VecDestroy(&ilink->x);CHKERRQ(ierr); 993 ierr = VecDestroy(&ilink->y);CHKERRQ(ierr); 994 ierr = VecDestroy(&ilink->z);CHKERRQ(ierr); 995 ierr = VecScatterDestroy(&ilink->sctx);CHKERRQ(ierr); 996 ierr = ISDestroy(&ilink->is);CHKERRQ(ierr); 997 ierr = ISDestroy(&ilink->is_col);CHKERRQ(ierr); 998 next = ilink->next; 999 ilink = next; 1000 } 1001 ierr = PetscFree2(jac->x,jac->y);CHKERRQ(ierr); 1002 if (jac->mat && jac->mat != jac->pmat) { 1003 ierr = MatDestroyMatrices(jac->nsplits,&jac->mat);CHKERRQ(ierr); 1004 } else if (jac->mat) { 1005 jac->mat = NULL; 1006 } 1007 if (jac->pmat) {ierr = MatDestroyMatrices(jac->nsplits,&jac->pmat);CHKERRQ(ierr);} 1008 if (jac->Afield) {ierr = MatDestroyMatrices(jac->nsplits,&jac->Afield);CHKERRQ(ierr);} 1009 ierr = VecDestroy(&jac->w1);CHKERRQ(ierr); 1010 ierr = VecDestroy(&jac->w2);CHKERRQ(ierr); 1011 ierr = MatDestroy(&jac->schur);CHKERRQ(ierr); 1012 ierr = MatDestroy(&jac->schur_user);CHKERRQ(ierr); 1013 ierr = KSPDestroy(&jac->kspschur);CHKERRQ(ierr); 1014 ierr = KSPDestroy(&jac->kspupper);CHKERRQ(ierr); 1015 ierr = MatDestroy(&jac->B);CHKERRQ(ierr); 1016 ierr = MatDestroy(&jac->C);CHKERRQ(ierr); 1017 jac->reset = PETSC_TRUE; 1018 PetscFunctionReturn(0); 1019 } 1020 1021 #undef __FUNCT__ 1022 #define __FUNCT__ "PCDestroy_FieldSplit" 1023 static PetscErrorCode PCDestroy_FieldSplit(PC pc) 1024 { 1025 PC_FieldSplit *jac = (PC_FieldSplit*)pc->data; 1026 PetscErrorCode ierr; 1027 PC_FieldSplitLink ilink = jac->head,next; 1028 1029 PetscFunctionBegin; 1030 ierr = PCReset_FieldSplit(pc);CHKERRQ(ierr); 1031 while (ilink) { 1032 ierr = KSPDestroy(&ilink->ksp);CHKERRQ(ierr); 1033 next = ilink->next; 1034 ierr = PetscFree(ilink->splitname);CHKERRQ(ierr); 1035 ierr = PetscFree(ilink->fields);CHKERRQ(ierr); 1036 ierr = PetscFree(ilink->fields_col);CHKERRQ(ierr); 1037 ierr = PetscFree(ilink);CHKERRQ(ierr); 1038 ilink = next; 1039 } 1040 ierr = PetscFree2(jac->x,jac->y);CHKERRQ(ierr); 1041 ierr = PetscFree(pc->data);CHKERRQ(ierr); 1042 ierr = PetscObjectComposeFunction((PetscObject)pc,"PCFieldSplitGetSubKSP_C",NULL);CHKERRQ(ierr); 1043 ierr = PetscObjectComposeFunction((PetscObject)pc,"PCFieldSplitSetFields_C",NULL);CHKERRQ(ierr); 1044 ierr = PetscObjectComposeFunction((PetscObject)pc,"PCFieldSplitSetIS_C",NULL);CHKERRQ(ierr); 1045 ierr = PetscObjectComposeFunction((PetscObject)pc,"PCFieldSplitSetType_C",NULL);CHKERRQ(ierr); 1046 ierr = PetscObjectComposeFunction((PetscObject)pc,"PCFieldSplitSetBlockSize_C",NULL);CHKERRQ(ierr); 1047 ierr = PetscObjectComposeFunction((PetscObject)pc,"PCFieldSplitSchurPrecondition_C",NULL);CHKERRQ(ierr); 1048 ierr = PetscObjectComposeFunction((PetscObject)pc,"PCFieldSplitSetSchurFactType_C",NULL);CHKERRQ(ierr); 1049 PetscFunctionReturn(0); 1050 } 1051 1052 #undef __FUNCT__ 1053 #define __FUNCT__ "PCSetFromOptions_FieldSplit" 1054 static PetscErrorCode PCSetFromOptions_FieldSplit(PC pc) 1055 { 1056 PetscErrorCode ierr; 1057 PetscInt bs; 1058 PetscBool flg,stokes = PETSC_FALSE; 1059 PC_FieldSplit *jac = (PC_FieldSplit*)pc->data; 1060 PCCompositeType ctype; 1061 1062 PetscFunctionBegin; 1063 ierr = PetscOptionsHead("FieldSplit options");CHKERRQ(ierr); 1064 ierr = PetscOptionsBool("-pc_fieldsplit_dm_splits","Whether to use DMCreateFieldDecomposition() for splits","PCFieldSplitSetDMSplits",jac->dm_splits,&jac->dm_splits,NULL);CHKERRQ(ierr); 1065 ierr = PetscOptionsInt("-pc_fieldsplit_block_size","Blocksize that defines number of fields","PCFieldSplitSetBlockSize",jac->bs,&bs,&flg);CHKERRQ(ierr); 1066 if (flg) { 1067 ierr = PCFieldSplitSetBlockSize(pc,bs);CHKERRQ(ierr); 1068 } 1069 1070 ierr = PetscOptionsGetBool(((PetscObject)pc)->prefix,"-pc_fieldsplit_detect_saddle_point",&stokes,NULL);CHKERRQ(ierr); 1071 if (stokes) { 1072 ierr = PCFieldSplitSetType(pc,PC_COMPOSITE_SCHUR);CHKERRQ(ierr); 1073 jac->schurpre = PC_FIELDSPLIT_SCHUR_PRE_SELF; 1074 } 1075 1076 ierr = PetscOptionsEnum("-pc_fieldsplit_type","Type of composition","PCFieldSplitSetType",PCCompositeTypes,(PetscEnum)jac->type,(PetscEnum*)&ctype,&flg);CHKERRQ(ierr); 1077 if (flg) { 1078 ierr = PCFieldSplitSetType(pc,ctype);CHKERRQ(ierr); 1079 } 1080 /* Only setup fields once */ 1081 if ((jac->bs > 0) && (jac->nsplits == 0)) { 1082 /* only allow user to set fields from command line if bs is already known. 1083 otherwise user can set them in PCFieldSplitSetDefaults() */ 1084 ierr = PCFieldSplitSetRuntimeSplits_Private(pc);CHKERRQ(ierr); 1085 if (jac->splitdefined) {ierr = PetscInfo(pc,"Splits defined using the options database\n");CHKERRQ(ierr);} 1086 } 1087 if (jac->type == PC_COMPOSITE_SCHUR) { 1088 ierr = PetscOptionsGetEnum(((PetscObject)pc)->prefix,"-pc_fieldsplit_schur_factorization_type",PCFieldSplitSchurFactTypes,(PetscEnum*)&jac->schurfactorization,&flg);CHKERRQ(ierr); 1089 if (flg) {ierr = PetscInfo(pc,"Deprecated use of -pc_fieldsplit_schur_factorization_type\n");CHKERRQ(ierr);} 1090 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); 1091 ierr = PetscOptionsEnum("-pc_fieldsplit_schur_precondition","How to build preconditioner for Schur complement","PCFieldSplitSchurPrecondition",PCFieldSplitSchurPreTypes,(PetscEnum)jac->schurpre,(PetscEnum*)&jac->schurpre,NULL);CHKERRQ(ierr); 1092 } 1093 ierr = PetscOptionsTail();CHKERRQ(ierr); 1094 PetscFunctionReturn(0); 1095 } 1096 1097 /*------------------------------------------------------------------------------------*/ 1098 1099 #undef __FUNCT__ 1100 #define __FUNCT__ "PCFieldSplitSetFields_FieldSplit" 1101 static PetscErrorCode PCFieldSplitSetFields_FieldSplit(PC pc,const char splitname[],PetscInt n,const PetscInt *fields,const PetscInt *fields_col) 1102 { 1103 PC_FieldSplit *jac = (PC_FieldSplit*)pc->data; 1104 PetscErrorCode ierr; 1105 PC_FieldSplitLink ilink,next = jac->head; 1106 char prefix[128]; 1107 PetscInt i; 1108 1109 PetscFunctionBegin; 1110 if (jac->splitdefined) { 1111 ierr = PetscInfo1(pc,"Ignoring new split \"%s\" because the splits have already been defined\n",splitname);CHKERRQ(ierr); 1112 PetscFunctionReturn(0); 1113 } 1114 for (i=0; i<n; i++) { 1115 if (fields[i] >= jac->bs) SETERRQ2(PETSC_COMM_SELF,PETSC_ERR_ARG_OUTOFRANGE,"Field %D requested but only %D exist",fields[i],jac->bs); 1116 if (fields[i] < 0) SETERRQ1(PETSC_COMM_SELF,PETSC_ERR_ARG_OUTOFRANGE,"Negative field %D requested",fields[i]); 1117 } 1118 ierr = PetscNew(&ilink);CHKERRQ(ierr); 1119 if (splitname) { 1120 ierr = PetscStrallocpy(splitname,&ilink->splitname);CHKERRQ(ierr); 1121 } else { 1122 ierr = PetscMalloc1(3,&ilink->splitname);CHKERRQ(ierr); 1123 ierr = PetscSNPrintf(ilink->splitname,2,"%s",jac->nsplits);CHKERRQ(ierr); 1124 } 1125 ierr = PetscMalloc1(n,&ilink->fields);CHKERRQ(ierr); 1126 ierr = PetscMemcpy(ilink->fields,fields,n*sizeof(PetscInt));CHKERRQ(ierr); 1127 ierr = PetscMalloc1(n,&ilink->fields_col);CHKERRQ(ierr); 1128 ierr = PetscMemcpy(ilink->fields_col,fields_col,n*sizeof(PetscInt));CHKERRQ(ierr); 1129 1130 ilink->nfields = n; 1131 ilink->next = NULL; 1132 ierr = KSPCreate(PetscObjectComm((PetscObject)pc),&ilink->ksp);CHKERRQ(ierr); 1133 ierr = PetscObjectIncrementTabLevel((PetscObject)ilink->ksp,(PetscObject)pc,1);CHKERRQ(ierr); 1134 ierr = KSPSetType(ilink->ksp,KSPPREONLY);CHKERRQ(ierr); 1135 ierr = PetscLogObjectParent((PetscObject)pc,(PetscObject)ilink->ksp);CHKERRQ(ierr); 1136 1137 ierr = PetscSNPrintf(prefix,sizeof(prefix),"%sfieldsplit_%s_",((PetscObject)pc)->prefix ? ((PetscObject)pc)->prefix : "",ilink->splitname);CHKERRQ(ierr); 1138 ierr = KSPSetOptionsPrefix(ilink->ksp,prefix);CHKERRQ(ierr); 1139 1140 if (!next) { 1141 jac->head = ilink; 1142 ilink->previous = NULL; 1143 } else { 1144 while (next->next) { 1145 next = next->next; 1146 } 1147 next->next = ilink; 1148 ilink->previous = next; 1149 } 1150 jac->nsplits++; 1151 PetscFunctionReturn(0); 1152 } 1153 1154 #undef __FUNCT__ 1155 #define __FUNCT__ "PCFieldSplitGetSubKSP_FieldSplit_Schur" 1156 static PetscErrorCode PCFieldSplitGetSubKSP_FieldSplit_Schur(PC pc,PetscInt *n,KSP **subksp) 1157 { 1158 PC_FieldSplit *jac = (PC_FieldSplit*)pc->data; 1159 PetscErrorCode ierr; 1160 1161 PetscFunctionBegin; 1162 ierr = PetscMalloc1(jac->nsplits,subksp);CHKERRQ(ierr); 1163 ierr = MatSchurComplementGetKSP(jac->schur,*subksp);CHKERRQ(ierr); 1164 1165 (*subksp)[1] = jac->kspschur; 1166 if (n) *n = jac->nsplits; 1167 PetscFunctionReturn(0); 1168 } 1169 1170 #undef __FUNCT__ 1171 #define __FUNCT__ "PCFieldSplitGetSubKSP_FieldSplit" 1172 static PetscErrorCode PCFieldSplitGetSubKSP_FieldSplit(PC pc,PetscInt *n,KSP **subksp) 1173 { 1174 PC_FieldSplit *jac = (PC_FieldSplit*)pc->data; 1175 PetscErrorCode ierr; 1176 PetscInt cnt = 0; 1177 PC_FieldSplitLink ilink = jac->head; 1178 1179 PetscFunctionBegin; 1180 ierr = PetscMalloc1(jac->nsplits,subksp);CHKERRQ(ierr); 1181 while (ilink) { 1182 (*subksp)[cnt++] = ilink->ksp; 1183 ilink = ilink->next; 1184 } 1185 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); 1186 if (n) *n = jac->nsplits; 1187 PetscFunctionReturn(0); 1188 } 1189 1190 #undef __FUNCT__ 1191 #define __FUNCT__ "PCFieldSplitSetIS_FieldSplit" 1192 static PetscErrorCode PCFieldSplitSetIS_FieldSplit(PC pc,const char splitname[],IS is) 1193 { 1194 PC_FieldSplit *jac = (PC_FieldSplit*)pc->data; 1195 PetscErrorCode ierr; 1196 PC_FieldSplitLink ilink, next = jac->head; 1197 char prefix[128]; 1198 1199 PetscFunctionBegin; 1200 if (jac->splitdefined) { 1201 ierr = PetscInfo1(pc,"Ignoring new split \"%s\" because the splits have already been defined\n",splitname);CHKERRQ(ierr); 1202 PetscFunctionReturn(0); 1203 } 1204 ierr = PetscNew(&ilink);CHKERRQ(ierr); 1205 if (splitname) { 1206 ierr = PetscStrallocpy(splitname,&ilink->splitname);CHKERRQ(ierr); 1207 } else { 1208 ierr = PetscMalloc1(8,&ilink->splitname);CHKERRQ(ierr); 1209 ierr = PetscSNPrintf(ilink->splitname,7,"%D",jac->nsplits);CHKERRQ(ierr); 1210 } 1211 ierr = PetscObjectReference((PetscObject)is);CHKERRQ(ierr); 1212 ierr = ISDestroy(&ilink->is);CHKERRQ(ierr); 1213 ilink->is = is; 1214 ierr = PetscObjectReference((PetscObject)is);CHKERRQ(ierr); 1215 ierr = ISDestroy(&ilink->is_col);CHKERRQ(ierr); 1216 ilink->is_col = is; 1217 ilink->next = NULL; 1218 ierr = KSPCreate(PetscObjectComm((PetscObject)pc),&ilink->ksp);CHKERRQ(ierr); 1219 ierr = PetscObjectIncrementTabLevel((PetscObject)ilink->ksp,(PetscObject)pc,1);CHKERRQ(ierr); 1220 ierr = KSPSetType(ilink->ksp,KSPPREONLY);CHKERRQ(ierr); 1221 ierr = PetscLogObjectParent((PetscObject)pc,(PetscObject)ilink->ksp);CHKERRQ(ierr); 1222 1223 ierr = PetscSNPrintf(prefix,sizeof(prefix),"%sfieldsplit_%s_",((PetscObject)pc)->prefix ? ((PetscObject)pc)->prefix : "",ilink->splitname);CHKERRQ(ierr); 1224 ierr = KSPSetOptionsPrefix(ilink->ksp,prefix);CHKERRQ(ierr); 1225 1226 if (!next) { 1227 jac->head = ilink; 1228 ilink->previous = NULL; 1229 } else { 1230 while (next->next) { 1231 next = next->next; 1232 } 1233 next->next = ilink; 1234 ilink->previous = next; 1235 } 1236 jac->nsplits++; 1237 PetscFunctionReturn(0); 1238 } 1239 1240 #undef __FUNCT__ 1241 #define __FUNCT__ "PCFieldSplitSetFields" 1242 /*@ 1243 PCFieldSplitSetFields - Sets the fields for one particular split in the field split preconditioner 1244 1245 Logically Collective on PC 1246 1247 Input Parameters: 1248 + pc - the preconditioner context 1249 . splitname - name of this split, if NULL the number of the split is used 1250 . n - the number of fields in this split 1251 - fields - the fields in this split 1252 1253 Level: intermediate 1254 1255 Notes: Use PCFieldSplitSetIS() to set a completely general set of indices as a field. 1256 1257 The PCFieldSplitSetFields() is for defining fields as strided blocks. For example, if the block 1258 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 1259 0xx3xx6xx9xx12 ... x1xx4xx7xx ... xx2xx5xx8xx.. 01x34x67x... 0x1x3x5x7.. x12x45x78x.... 1260 where the numbered entries indicate what is in the field. 1261 1262 This function is called once per split (it creates a new split each time). Solve options 1263 for this split will be available under the prefix -fieldsplit_SPLITNAME_. 1264 1265 Developer Note: This routine does not actually create the IS representing the split, that is delayed 1266 until PCSetUp_FieldSplit(), because information about the vector/matrix layouts may not be 1267 available when this routine is called. 1268 1269 .seealso: PCFieldSplitGetSubKSP(), PCFIELDSPLIT, PCFieldSplitSetBlockSize(), PCFieldSplitSetIS() 1270 1271 @*/ 1272 PetscErrorCode PCFieldSplitSetFields(PC pc,const char splitname[],PetscInt n,const PetscInt *fields,const PetscInt *fields_col) 1273 { 1274 PetscErrorCode ierr; 1275 1276 PetscFunctionBegin; 1277 PetscValidHeaderSpecific(pc,PC_CLASSID,1); 1278 PetscValidCharPointer(splitname,2); 1279 if (n < 1) SETERRQ2(PetscObjectComm((PetscObject)pc),PETSC_ERR_ARG_OUTOFRANGE,"Provided number of fields %D in split \"%s\" not positive",n,splitname); 1280 PetscValidIntPointer(fields,3); 1281 ierr = PetscTryMethod(pc,"PCFieldSplitSetFields_C",(PC,const char[],PetscInt,const PetscInt*,const PetscInt*),(pc,splitname,n,fields,fields_col));CHKERRQ(ierr); 1282 PetscFunctionReturn(0); 1283 } 1284 1285 #undef __FUNCT__ 1286 #define __FUNCT__ "PCFieldSplitSetIS" 1287 /*@ 1288 PCFieldSplitSetIS - Sets the exact elements for field 1289 1290 Logically Collective on PC 1291 1292 Input Parameters: 1293 + pc - the preconditioner context 1294 . splitname - name of this split, if NULL the number of the split is used 1295 - is - the index set that defines the vector elements in this field 1296 1297 1298 Notes: 1299 Use PCFieldSplitSetFields(), for fields defined by strided types. 1300 1301 This function is called once per split (it creates a new split each time). Solve options 1302 for this split will be available under the prefix -fieldsplit_SPLITNAME_. 1303 1304 Level: intermediate 1305 1306 .seealso: PCFieldSplitGetSubKSP(), PCFIELDSPLIT, PCFieldSplitSetBlockSize() 1307 1308 @*/ 1309 PetscErrorCode PCFieldSplitSetIS(PC pc,const char splitname[],IS is) 1310 { 1311 PetscErrorCode ierr; 1312 1313 PetscFunctionBegin; 1314 PetscValidHeaderSpecific(pc,PC_CLASSID,1); 1315 if (splitname) PetscValidCharPointer(splitname,2); 1316 PetscValidHeaderSpecific(is,IS_CLASSID,3); 1317 ierr = PetscTryMethod(pc,"PCFieldSplitSetIS_C",(PC,const char[],IS),(pc,splitname,is));CHKERRQ(ierr); 1318 PetscFunctionReturn(0); 1319 } 1320 1321 #undef __FUNCT__ 1322 #define __FUNCT__ "PCFieldSplitGetIS" 1323 /*@ 1324 PCFieldSplitGetIS - Retrieves the elements for a field as an IS 1325 1326 Logically Collective on PC 1327 1328 Input Parameters: 1329 + pc - the preconditioner context 1330 - splitname - name of this split 1331 1332 Output Parameter: 1333 - is - the index set that defines the vector elements in this field, or NULL if the field is not found 1334 1335 Level: intermediate 1336 1337 .seealso: PCFieldSplitGetSubKSP(), PCFIELDSPLIT, PCFieldSplitSetIS() 1338 1339 @*/ 1340 PetscErrorCode PCFieldSplitGetIS(PC pc,const char splitname[],IS *is) 1341 { 1342 PetscErrorCode ierr; 1343 1344 PetscFunctionBegin; 1345 PetscValidHeaderSpecific(pc,PC_CLASSID,1); 1346 PetscValidCharPointer(splitname,2); 1347 PetscValidPointer(is,3); 1348 { 1349 PC_FieldSplit *jac = (PC_FieldSplit*) pc->data; 1350 PC_FieldSplitLink ilink = jac->head; 1351 PetscBool found; 1352 1353 *is = NULL; 1354 while (ilink) { 1355 ierr = PetscStrcmp(ilink->splitname, splitname, &found);CHKERRQ(ierr); 1356 if (found) { 1357 *is = ilink->is; 1358 break; 1359 } 1360 ilink = ilink->next; 1361 } 1362 } 1363 PetscFunctionReturn(0); 1364 } 1365 1366 #undef __FUNCT__ 1367 #define __FUNCT__ "PCFieldSplitSetBlockSize" 1368 /*@ 1369 PCFieldSplitSetBlockSize - Sets the block size for defining where fields start in the 1370 fieldsplit preconditioner. If not set the matrix block size is used. 1371 1372 Logically Collective on PC 1373 1374 Input Parameters: 1375 + pc - the preconditioner context 1376 - bs - the block size 1377 1378 Level: intermediate 1379 1380 .seealso: PCFieldSplitGetSubKSP(), PCFIELDSPLIT, PCFieldSplitSetFields() 1381 1382 @*/ 1383 PetscErrorCode PCFieldSplitSetBlockSize(PC pc,PetscInt bs) 1384 { 1385 PetscErrorCode ierr; 1386 1387 PetscFunctionBegin; 1388 PetscValidHeaderSpecific(pc,PC_CLASSID,1); 1389 PetscValidLogicalCollectiveInt(pc,bs,2); 1390 ierr = PetscTryMethod(pc,"PCFieldSplitSetBlockSize_C",(PC,PetscInt),(pc,bs));CHKERRQ(ierr); 1391 PetscFunctionReturn(0); 1392 } 1393 1394 #undef __FUNCT__ 1395 #define __FUNCT__ "PCFieldSplitGetSubKSP" 1396 /*@C 1397 PCFieldSplitGetSubKSP - Gets the KSP contexts for all splits 1398 1399 Collective on KSP 1400 1401 Input Parameter: 1402 . pc - the preconditioner context 1403 1404 Output Parameters: 1405 + n - the number of splits 1406 - pc - the array of KSP contexts 1407 1408 Note: 1409 After PCFieldSplitGetSubKSP() the array of KSPs IS to be freed by the user 1410 (not the KSP just the array that contains them). 1411 1412 You must call KSPSetUp() before calling PCFieldSplitGetSubKSP(). 1413 1414 Fortran Usage: You must pass in a KSP array that is large enough to contain all the local KSPs. 1415 You can call PCFieldSplitGetSubKSP(pc,n,NULL_OBJECT,ierr) to determine how large the 1416 KSP array must be. 1417 1418 1419 Level: advanced 1420 1421 .seealso: PCFIELDSPLIT 1422 @*/ 1423 PetscErrorCode PCFieldSplitGetSubKSP(PC pc,PetscInt *n,KSP *subksp[]) 1424 { 1425 PetscErrorCode ierr; 1426 1427 PetscFunctionBegin; 1428 PetscValidHeaderSpecific(pc,PC_CLASSID,1); 1429 if (n) PetscValidIntPointer(n,2); 1430 ierr = PetscUseMethod(pc,"PCFieldSplitGetSubKSP_C",(PC,PetscInt*,KSP **),(pc,n,subksp));CHKERRQ(ierr); 1431 PetscFunctionReturn(0); 1432 } 1433 1434 #undef __FUNCT__ 1435 #define __FUNCT__ "PCFieldSplitSchurPrecondition" 1436 /*@ 1437 PCFieldSplitSchurPrecondition - Indicates if the Schur complement is preconditioned by a preconditioner constructed by the 1438 A11 matrix. Otherwise no preconditioner is used. 1439 1440 Collective on PC 1441 1442 Input Parameters: 1443 + pc - the preconditioner context 1444 . ptype - which matrix to use for preconditioning the Schur complement, PC_FIELDSPLIT_SCHUR_PRE_A11 (diag) is default 1445 - userpre - matrix to use for preconditioning, or NULL 1446 1447 Options Database: 1448 . -pc_fieldsplit_schur_precondition <self,user,a11> default is a11 1449 1450 Notes: 1451 $ If ptype is 1452 $ user then the preconditioner for the Schur complement is generated by the provided matrix (pre argument 1453 $ to this function). 1454 $ a11 then the preconditioner for the Schur complement is generated by the block diagonal part of the original 1455 $ matrix associated with the Schur complement (i.e. A11) 1456 $ self the preconditioner for the Schur complement is generated from the Schur complement matrix itself: 1457 $ The only preconditioner that currently works directly with the Schur complement matrix object is the PCLSC 1458 $ preconditioner 1459 1460 When solving a saddle point problem, where the A11 block is identically zero, using a11 as the ptype only makes sense 1461 with the additional option -fieldsplit_1_pc_type none. Usually for saddle point problems one would use a ptype of self and 1462 -fieldsplit_1_pc_type lsc which uses the least squares commutator compute a preconditioner for the Schur complement. 1463 1464 Developer Notes: This is a terrible name, gives no good indication of what the function does and should also have Set in 1465 the name since it sets a proceedure to use. 1466 1467 Level: intermediate 1468 1469 .seealso: PCFieldSplitGetSubKSP(), PCFIELDSPLIT, PCFieldSplitSetFields(), PCFieldSplitSchurPreType, PCLSC 1470 1471 @*/ 1472 PetscErrorCode PCFieldSplitSchurPrecondition(PC pc,PCFieldSplitSchurPreType ptype,Mat pre) 1473 { 1474 PetscErrorCode ierr; 1475 1476 PetscFunctionBegin; 1477 PetscValidHeaderSpecific(pc,PC_CLASSID,1); 1478 ierr = PetscTryMethod(pc,"PCFieldSplitSchurPrecondition_C",(PC,PCFieldSplitSchurPreType,Mat),(pc,ptype,pre));CHKERRQ(ierr); 1479 PetscFunctionReturn(0); 1480 } 1481 1482 #undef __FUNCT__ 1483 #define __FUNCT__ "PCFieldSplitSchurPrecondition_FieldSplit" 1484 static PetscErrorCode PCFieldSplitSchurPrecondition_FieldSplit(PC pc,PCFieldSplitSchurPreType ptype,Mat pre) 1485 { 1486 PC_FieldSplit *jac = (PC_FieldSplit*)pc->data; 1487 PetscErrorCode ierr; 1488 1489 PetscFunctionBegin; 1490 jac->schurpre = ptype; 1491 if (pre) { 1492 ierr = MatDestroy(&jac->schur_user);CHKERRQ(ierr); 1493 jac->schur_user = pre; 1494 ierr = PetscObjectReference((PetscObject)jac->schur_user);CHKERRQ(ierr); 1495 } 1496 PetscFunctionReturn(0); 1497 } 1498 1499 #undef __FUNCT__ 1500 #define __FUNCT__ "PCFieldSplitSetSchurFactType" 1501 /*@ 1502 PCFieldSplitSetSchurFactType - sets which blocks of the approximate block factorization to retain 1503 1504 Collective on PC 1505 1506 Input Parameters: 1507 + pc - the preconditioner context 1508 - ftype - which blocks of factorization to retain, PC_FIELDSPLIT_SCHUR_FACT_FULL is default 1509 1510 Options Database: 1511 . -pc_fieldsplit_schur_fact_type <diag,lower,upper,full> default is full 1512 1513 1514 Level: intermediate 1515 1516 Notes: 1517 The FULL factorization is 1518 1519 $ (A B) = (1 0) (A 0) (1 Ainv*B) 1520 $ (C D) (C*Ainv 1) (0 S) (0 1 ) 1521 1522 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, 1523 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). 1524 1525 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 1526 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 1527 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, 1528 the preconditioned operator has three distinct nonzero eigenvalues and minimal polynomial of degree at most 4, so KSPGMRES converges in at most 4 iterations. 1529 1530 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 1531 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). 1532 1533 References: 1534 Murphy, Golub, and Wathen, A note on preconditioning indefinite linear systems, SIAM J. Sci. Comput., 21 (2000) pp. 1969-1972. 1535 1536 Ipsen, A note on preconditioning nonsymmetric matrices, SIAM J. Sci. Comput., 23 (2001), pp. 1050-1051. 1537 1538 .seealso: PCFieldSplitGetSubKSP(), PCFIELDSPLIT, PCFieldSplitSetFields(), PCFieldSplitSchurPreType 1539 @*/ 1540 PetscErrorCode PCFieldSplitSetSchurFactType(PC pc,PCFieldSplitSchurFactType ftype) 1541 { 1542 PetscErrorCode ierr; 1543 1544 PetscFunctionBegin; 1545 PetscValidHeaderSpecific(pc,PC_CLASSID,1); 1546 ierr = PetscTryMethod(pc,"PCFieldSplitSetSchurFactType_C",(PC,PCFieldSplitSchurFactType),(pc,ftype));CHKERRQ(ierr); 1547 PetscFunctionReturn(0); 1548 } 1549 1550 #undef __FUNCT__ 1551 #define __FUNCT__ "PCFieldSplitSetSchurFactType_FieldSplit" 1552 static PetscErrorCode PCFieldSplitSetSchurFactType_FieldSplit(PC pc,PCFieldSplitSchurFactType ftype) 1553 { 1554 PC_FieldSplit *jac = (PC_FieldSplit*)pc->data; 1555 1556 PetscFunctionBegin; 1557 jac->schurfactorization = ftype; 1558 PetscFunctionReturn(0); 1559 } 1560 1561 #undef __FUNCT__ 1562 #define __FUNCT__ "PCFieldSplitGetSchurBlocks" 1563 /*@C 1564 PCFieldSplitGetSchurBlocks - Gets all matrix blocks for the Schur complement 1565 1566 Collective on KSP 1567 1568 Input Parameter: 1569 . pc - the preconditioner context 1570 1571 Output Parameters: 1572 + A00 - the (0,0) block 1573 . A01 - the (0,1) block 1574 . A10 - the (1,0) block 1575 - A11 - the (1,1) block 1576 1577 Level: advanced 1578 1579 .seealso: PCFIELDSPLIT 1580 @*/ 1581 PetscErrorCode PCFieldSplitGetSchurBlocks(PC pc,Mat *A00,Mat *A01,Mat *A10, Mat *A11) 1582 { 1583 PC_FieldSplit *jac = (PC_FieldSplit*) pc->data; 1584 1585 PetscFunctionBegin; 1586 PetscValidHeaderSpecific(pc,PC_CLASSID,1); 1587 if (jac->type != PC_COMPOSITE_SCHUR) SETERRQ(PetscObjectComm((PetscObject)pc),PETSC_ERR_ARG_WRONG, "FieldSplit is not using a Schur complement approach."); 1588 if (A00) *A00 = jac->pmat[0]; 1589 if (A01) *A01 = jac->B; 1590 if (A10) *A10 = jac->C; 1591 if (A11) *A11 = jac->pmat[1]; 1592 PetscFunctionReturn(0); 1593 } 1594 1595 #undef __FUNCT__ 1596 #define __FUNCT__ "PCFieldSplitSetType_FieldSplit" 1597 static PetscErrorCode PCFieldSplitSetType_FieldSplit(PC pc,PCCompositeType type) 1598 { 1599 PC_FieldSplit *jac = (PC_FieldSplit*)pc->data; 1600 PetscErrorCode ierr; 1601 1602 PetscFunctionBegin; 1603 jac->type = type; 1604 if (type == PC_COMPOSITE_SCHUR) { 1605 pc->ops->apply = PCApply_FieldSplit_Schur; 1606 pc->ops->view = PCView_FieldSplit_Schur; 1607 1608 ierr = PetscObjectComposeFunction((PetscObject)pc,"PCFieldSplitGetSubKSP_C",PCFieldSplitGetSubKSP_FieldSplit_Schur);CHKERRQ(ierr); 1609 ierr = PetscObjectComposeFunction((PetscObject)pc,"PCFieldSplitSchurPrecondition_C",PCFieldSplitSchurPrecondition_FieldSplit);CHKERRQ(ierr); 1610 ierr = PetscObjectComposeFunction((PetscObject)pc,"PCFieldSplitSetSchurFactType_C",PCFieldSplitSetSchurFactType_FieldSplit);CHKERRQ(ierr); 1611 1612 } else { 1613 pc->ops->apply = PCApply_FieldSplit; 1614 pc->ops->view = PCView_FieldSplit; 1615 1616 ierr = PetscObjectComposeFunction((PetscObject)pc,"PCFieldSplitGetSubKSP_C",PCFieldSplitGetSubKSP_FieldSplit);CHKERRQ(ierr); 1617 ierr = PetscObjectComposeFunction((PetscObject)pc,"PCFieldSplitSchurPrecondition_C",0);CHKERRQ(ierr); 1618 ierr = PetscObjectComposeFunction((PetscObject)pc,"PCFieldSplitSetSchurFactType_C",0);CHKERRQ(ierr); 1619 } 1620 PetscFunctionReturn(0); 1621 } 1622 1623 #undef __FUNCT__ 1624 #define __FUNCT__ "PCFieldSplitSetBlockSize_FieldSplit" 1625 static PetscErrorCode PCFieldSplitSetBlockSize_FieldSplit(PC pc,PetscInt bs) 1626 { 1627 PC_FieldSplit *jac = (PC_FieldSplit*)pc->data; 1628 1629 PetscFunctionBegin; 1630 if (bs < 1) SETERRQ1(PetscObjectComm((PetscObject)pc),PETSC_ERR_ARG_OUTOFRANGE,"Blocksize must be positive, you gave %D",bs); 1631 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); 1632 jac->bs = bs; 1633 PetscFunctionReturn(0); 1634 } 1635 1636 #undef __FUNCT__ 1637 #define __FUNCT__ "PCFieldSplitSetType" 1638 /*@ 1639 PCFieldSplitSetType - Sets the type of fieldsplit preconditioner. 1640 1641 Collective on PC 1642 1643 Input Parameter: 1644 . pc - the preconditioner context 1645 . type - PC_COMPOSITE_ADDITIVE, PC_COMPOSITE_MULTIPLICATIVE (default), PC_COMPOSITE_SYMMETRIC_MULTIPLICATIVE, PC_COMPOSITE_SPECIAL, PC_COMPOSITE_SCHUR 1646 1647 Options Database Key: 1648 . -pc_fieldsplit_type <type: one of multiplicative, additive, symmetric_multiplicative, special, schur> - Sets fieldsplit preconditioner type 1649 1650 Level: Intermediate 1651 1652 .keywords: PC, set, type, composite preconditioner, additive, multiplicative 1653 1654 .seealso: PCCompositeSetType() 1655 1656 @*/ 1657 PetscErrorCode PCFieldSplitSetType(PC pc,PCCompositeType type) 1658 { 1659 PetscErrorCode ierr; 1660 1661 PetscFunctionBegin; 1662 PetscValidHeaderSpecific(pc,PC_CLASSID,1); 1663 ierr = PetscTryMethod(pc,"PCFieldSplitSetType_C",(PC,PCCompositeType),(pc,type));CHKERRQ(ierr); 1664 PetscFunctionReturn(0); 1665 } 1666 1667 #undef __FUNCT__ 1668 #define __FUNCT__ "PCFieldSplitGetType" 1669 /*@ 1670 PCFieldSplitGetType - Gets the type of fieldsplit preconditioner. 1671 1672 Not collective 1673 1674 Input Parameter: 1675 . pc - the preconditioner context 1676 1677 Output Parameter: 1678 . type - PC_COMPOSITE_ADDITIVE, PC_COMPOSITE_MULTIPLICATIVE (default), PC_COMPOSITE_SYMMETRIC_MULTIPLICATIVE, PC_COMPOSITE_SPECIAL, PC_COMPOSITE_SCHUR 1679 1680 Level: Intermediate 1681 1682 .keywords: PC, set, type, composite preconditioner, additive, multiplicative 1683 .seealso: PCCompositeSetType() 1684 @*/ 1685 PetscErrorCode PCFieldSplitGetType(PC pc, PCCompositeType *type) 1686 { 1687 PC_FieldSplit *jac = (PC_FieldSplit*) pc->data; 1688 1689 PetscFunctionBegin; 1690 PetscValidHeaderSpecific(pc,PC_CLASSID,1); 1691 PetscValidIntPointer(type,2); 1692 *type = jac->type; 1693 PetscFunctionReturn(0); 1694 } 1695 1696 #undef __FUNCT__ 1697 #define __FUNCT__ "PCFieldSplitSetDMSplits" 1698 /*@ 1699 PCFieldSplitSetDMSplits - Flags whether DMCreateFieldDecomposition() should be used to define the splits, whenever possible. 1700 1701 Logically Collective 1702 1703 Input Parameters: 1704 + pc - the preconditioner context 1705 - flg - boolean indicating whether to use field splits defined by the DM 1706 1707 Options Database Key: 1708 . -pc_fieldsplit_dm_splits 1709 1710 Level: Intermediate 1711 1712 .keywords: PC, DM, composite preconditioner, additive, multiplicative 1713 1714 .seealso: PCFieldSplitGetDMSplits() 1715 1716 @*/ 1717 PetscErrorCode PCFieldSplitSetDMSplits(PC pc,PetscBool flg) 1718 { 1719 PC_FieldSplit *jac = (PC_FieldSplit*)pc->data; 1720 PetscBool isfs; 1721 PetscErrorCode ierr; 1722 1723 PetscFunctionBegin; 1724 PetscValidHeaderSpecific(pc,PC_CLASSID,1); 1725 PetscValidLogicalCollectiveBool(pc,flg,2); 1726 ierr = PetscObjectTypeCompare((PetscObject)pc,PCFIELDSPLIT,&isfs);CHKERRQ(ierr); 1727 if (isfs) { 1728 jac->dm_splits = flg; 1729 } 1730 PetscFunctionReturn(0); 1731 } 1732 1733 1734 #undef __FUNCT__ 1735 #define __FUNCT__ "PCFieldSplitGetDMSplits" 1736 /*@ 1737 PCFieldSplitGetDMSplits - Returns flag indicating whether DMCreateFieldDecomposition() should be used to define the splits, whenever possible. 1738 1739 Logically Collective 1740 1741 Input Parameter: 1742 . pc - the preconditioner context 1743 1744 Output Parameter: 1745 . flg - boolean indicating whether to use field splits defined by the DM 1746 1747 Level: Intermediate 1748 1749 .keywords: PC, DM, composite preconditioner, additive, multiplicative 1750 1751 .seealso: PCFieldSplitSetDMSplits() 1752 1753 @*/ 1754 PetscErrorCode PCFieldSplitGetDMSplits(PC pc,PetscBool* flg) 1755 { 1756 PC_FieldSplit *jac = (PC_FieldSplit*)pc->data; 1757 PetscBool isfs; 1758 PetscErrorCode ierr; 1759 1760 PetscFunctionBegin; 1761 PetscValidHeaderSpecific(pc,PC_CLASSID,1); 1762 PetscValidPointer(flg,2); 1763 ierr = PetscObjectTypeCompare((PetscObject)pc,PCFIELDSPLIT,&isfs);CHKERRQ(ierr); 1764 if (isfs) { 1765 if(flg) *flg = jac->dm_splits; 1766 } 1767 PetscFunctionReturn(0); 1768 } 1769 1770 /* -------------------------------------------------------------------------------------*/ 1771 /*MC 1772 PCFIELDSPLIT - Preconditioner created by combining separate preconditioners for individual 1773 fields or groups of fields. See the users manual section "Solving Block Matrices" for more details. 1774 1775 To set options on the solvers for each block append -fieldsplit_ to all the PC 1776 options database keys. For example, -fieldsplit_pc_type ilu -fieldsplit_pc_factor_levels 1 1777 1778 To set the options on the solvers separate for each block call PCFieldSplitGetSubKSP() 1779 and set the options directly on the resulting KSP object 1780 1781 Level: intermediate 1782 1783 Options Database Keys: 1784 + -pc_fieldsplit_%d_fields <a,b,..> - indicates the fields to be used in the %d'th split 1785 . -pc_fieldsplit_default - automatically add any fields to additional splits that have not 1786 been supplied explicitly by -pc_fieldsplit_%d_fields 1787 . -pc_fieldsplit_block_size <bs> - size of block that defines fields (i.e. there are bs fields) 1788 . -pc_fieldsplit_type <additive,multiplicative,symmetric_multiplicative,schur> - type of relaxation or factorization splitting 1789 . -pc_fieldsplit_schur_precondition <self,user,a11> - default is a11 1790 . -pc_fieldsplit_detect_saddle_point - automatically finds rows with zero or negative diagonal and uses Schur complement with no preconditioner as the solver 1791 1792 - Options prefix for inner solvers when using Schur complement preconditioner are -fieldsplit_0_ and -fieldsplit_1_ 1793 for all other solvers they are -fieldsplit_%d_ for the dth field, use -fieldsplit_ for all fields 1794 1795 Notes: 1796 Use PCFieldSplitSetFields() to set fields defined by "strided" entries and PCFieldSplitSetIS() 1797 to define a field by an arbitrary collection of entries. 1798 1799 If no fields are set the default is used. The fields are defined by entries strided by bs, 1800 beginning at 0 then 1, etc to bs-1. The block size can be set with PCFieldSplitSetBlockSize(), 1801 if this is not called the block size defaults to the blocksize of the second matrix passed 1802 to KSPSetOperators()/PCSetOperators(). 1803 1804 $ For the Schur complement preconditioner if J = ( A00 A01 ) 1805 $ ( A10 A11 ) 1806 $ the preconditioner using full factorization is 1807 $ ( I -A10 ksp(A00) ) ( inv(A00) 0 ) ( I 0 ) 1808 $ ( 0 I ) ( 0 ksp(S) ) ( -A10 ksp(A00) I ) 1809 where the action of inv(A00) is applied using the KSP solver with prefix -fieldsplit_0_. The action of 1810 ksp(S) is computed using the KSP solver with prefix -fieldsplit_splitname_ (where splitname was given 1811 in providing the SECOND split or 1 if not give). For PCFieldSplitGetKSP() when field number is 0, 1812 it returns the KSP associated with -fieldsplit_0_ while field number 1 gives -fieldsplit_1_ KSP. By default 1813 A11 is used to construct a preconditioner for S, use PCFieldSplitSchurPrecondition() to turn on or off this 1814 option. You can use the preconditioner PCLSC to precondition the Schur complement with -fieldsplit_1_pc_type lsc. The 1815 factorization type is set using -pc_fieldsplit_schur_fact_type <diag, lower, upper, full>. The full is shown above, 1816 diag gives 1817 $ ( inv(A00) 0 ) 1818 $ ( 0 -ksp(S) ) 1819 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 1820 $ ( A00 0 ) 1821 $ ( A10 S ) 1822 where the inverses of A00 and S are applied using KSPs. The upper factorization is the inverse of 1823 $ ( A00 A01 ) 1824 $ ( 0 S ) 1825 where again the inverses of A00 and S are applied using KSPs. 1826 1827 If only one set of indices (one IS) is provided with PCFieldSplitSetIS() then the complement of that IS 1828 is used automatically for a second block. 1829 1830 The fieldsplit preconditioner cannot currently be used with the BAIJ or SBAIJ data formats if the blocksize is larger than 1. 1831 Generally it should be used with the AIJ format. 1832 1833 The forms of these preconditioners are closely related if not identical to forms derived as "Distributive Iterations", see, 1834 for example, page 294 in "Principles of Computational Fluid Dynamics" by Pieter Wesseling. Note that one can also use PCFIELDSPLIT 1835 inside a smoother resulting in "Distributive Smoothers". 1836 1837 Concepts: physics based preconditioners, block preconditioners 1838 1839 .seealso: PCCreate(), PCSetType(), PCType (for list of available types), PC, Block_Preconditioners, PCLSC, 1840 PCFieldSplitGetSubKSP(), PCFieldSplitSetFields(), PCFieldSplitSetType(), PCFieldSplitSetIS(), PCFieldSplitSchurPrecondition() 1841 M*/ 1842 1843 #undef __FUNCT__ 1844 #define __FUNCT__ "PCCreate_FieldSplit" 1845 PETSC_EXTERN PetscErrorCode PCCreate_FieldSplit(PC pc) 1846 { 1847 PetscErrorCode ierr; 1848 PC_FieldSplit *jac; 1849 1850 PetscFunctionBegin; 1851 ierr = PetscNewLog(pc,&jac);CHKERRQ(ierr); 1852 1853 jac->bs = -1; 1854 jac->nsplits = 0; 1855 jac->type = PC_COMPOSITE_MULTIPLICATIVE; 1856 jac->schurpre = PC_FIELDSPLIT_SCHUR_PRE_USER; /* Try user preconditioner first, fall back on diagonal */ 1857 jac->schurfactorization = PC_FIELDSPLIT_SCHUR_FACT_FULL; 1858 jac->dm_splits = PETSC_TRUE; 1859 1860 pc->data = (void*)jac; 1861 1862 pc->ops->apply = PCApply_FieldSplit; 1863 pc->ops->applytranspose = PCApplyTranspose_FieldSplit; 1864 pc->ops->setup = PCSetUp_FieldSplit; 1865 pc->ops->reset = PCReset_FieldSplit; 1866 pc->ops->destroy = PCDestroy_FieldSplit; 1867 pc->ops->setfromoptions = PCSetFromOptions_FieldSplit; 1868 pc->ops->view = PCView_FieldSplit; 1869 pc->ops->applyrichardson = 0; 1870 1871 ierr = PetscObjectComposeFunction((PetscObject)pc,"PCFieldSplitGetSubKSP_C",PCFieldSplitGetSubKSP_FieldSplit);CHKERRQ(ierr); 1872 ierr = PetscObjectComposeFunction((PetscObject)pc,"PCFieldSplitSetFields_C",PCFieldSplitSetFields_FieldSplit);CHKERRQ(ierr); 1873 ierr = PetscObjectComposeFunction((PetscObject)pc,"PCFieldSplitSetIS_C",PCFieldSplitSetIS_FieldSplit);CHKERRQ(ierr); 1874 ierr = PetscObjectComposeFunction((PetscObject)pc,"PCFieldSplitSetType_C",PCFieldSplitSetType_FieldSplit);CHKERRQ(ierr); 1875 ierr = PetscObjectComposeFunction((PetscObject)pc,"PCFieldSplitSetBlockSize_C",PCFieldSplitSetBlockSize_FieldSplit);CHKERRQ(ierr); 1876 PetscFunctionReturn(0); 1877 } 1878 1879 1880 1881