1 #define PETSCKSP_DLL 2 3 /* 4 5 */ 6 #include "src/ksp/pc/pcimpl.h" /*I "petscpc.h" I*/ 7 8 typedef struct _PC_FieldSplitLink *PC_FieldSplitLink; 9 struct _PC_FieldSplitLink { 10 KSP ksp; 11 Vec x,y; 12 PetscInt nfields; 13 PetscInt *fields; 14 VecScatter sctx; 15 PC_FieldSplitLink next; 16 }; 17 18 typedef struct { 19 PCCompositeType type; /* additive or multiplicative */ 20 PetscTruth defaultsplit; 21 PetscInt bs; 22 PetscInt nsplits; 23 Vec *x,*y,w1,w2; 24 Mat *pmat; 25 IS *is; 26 PC_FieldSplitLink head; 27 } PC_FieldSplit; 28 29 #undef __FUNCT__ 30 #define __FUNCT__ "PCView_FieldSplit" 31 static PetscErrorCode PCView_FieldSplit(PC pc,PetscViewer viewer) 32 { 33 PC_FieldSplit *jac = (PC_FieldSplit*)pc->data; 34 PetscErrorCode ierr; 35 PetscTruth iascii; 36 PetscInt i,j; 37 PC_FieldSplitLink ilink = jac->head; 38 39 PetscFunctionBegin; 40 ierr = PetscTypeCompare((PetscObject)viewer,PETSC_VIEWER_ASCII,&iascii);CHKERRQ(ierr); 41 if (iascii) { 42 ierr = PetscViewerASCIIPrintf(viewer," FieldSplit with %s composition: total splits = %D",PCCompositeTypes[jac->type],jac->nsplits);CHKERRQ(ierr); 43 ierr = PetscViewerASCIIPrintf(viewer," Solver info for each split is in the following KSP objects:\n");CHKERRQ(ierr); 44 ierr = PetscViewerASCIIPushTab(viewer);CHKERRQ(ierr); 45 for (i=0; i<jac->nsplits; i++) { 46 ierr = PetscViewerASCIIPrintf(viewer,"Split number %D Fields ",i);CHKERRQ(ierr); 47 ierr = PetscViewerASCIIUseTabs(viewer,PETSC_FALSE);CHKERRQ(ierr); 48 for (j=0; j<ilink->nfields; j++) { 49 if (j > 0) { 50 ierr = PetscViewerASCIIPrintf(viewer,",");CHKERRQ(ierr); 51 } 52 ierr = PetscViewerASCIIPrintf(viewer," %D",ilink->fields[j]);CHKERRQ(ierr); 53 } 54 ierr = PetscViewerASCIIPrintf(viewer,"\n");CHKERRQ(ierr); 55 ierr = PetscViewerASCIIUseTabs(viewer,PETSC_TRUE);CHKERRQ(ierr); 56 ierr = KSPView(ilink->ksp,viewer);CHKERRQ(ierr); 57 ilink = ilink->next; 58 } 59 ierr = PetscViewerASCIIPopTab(viewer);CHKERRQ(ierr); 60 } else { 61 SETERRQ1(PETSC_ERR_SUP,"Viewer type %s not supported for PCFieldSplit",((PetscObject)viewer)->type_name); 62 } 63 PetscFunctionReturn(0); 64 } 65 66 #undef __FUNCT__ 67 #define __FUNCT__ "PCFieldSplitSetDefaults" 68 static PetscErrorCode PCFieldSplitSetDefaults(PC pc) 69 { 70 PC_FieldSplit *jac = (PC_FieldSplit*)pc->data; 71 PetscErrorCode ierr; 72 PC_FieldSplitLink ilink = jac->head; 73 PetscInt i; 74 PetscTruth flg = PETSC_FALSE,*fields; 75 76 PetscFunctionBegin; 77 ierr = PetscOptionsGetTruth(pc->prefix,"-pc_fieldsplit_default",&flg,PETSC_NULL);CHKERRQ(ierr); 78 if (!ilink || flg) { 79 ierr = PetscLogInfo((pc,"PCFieldSplitSetDefaults: Using default splitting of fields\n"));CHKERRQ(ierr); 80 if (jac->bs <= 0) { 81 ierr = MatGetBlockSize(pc->pmat,&jac->bs);CHKERRQ(ierr); 82 } 83 ierr = PetscMalloc(jac->bs*sizeof(PetscTruth),&fields);CHKERRQ(ierr); 84 ierr = PetscMemzero(fields,jac->bs*sizeof(PetscTruth));CHKERRQ(ierr); 85 while (ilink) { 86 for (i=0; i<ilink->nfields; i++) { 87 fields[ilink->fields[i]] = PETSC_TRUE; 88 } 89 ilink = ilink->next; 90 } 91 jac->defaultsplit = PETSC_TRUE; 92 for (i=0; i<jac->bs; i++) { 93 if (!fields[i]) { 94 ierr = PCFieldSplitSetFields(pc,1,&i);CHKERRQ(ierr); 95 } else { 96 jac->defaultsplit = PETSC_FALSE; 97 } 98 } 99 } 100 PetscFunctionReturn(0); 101 } 102 103 104 #undef __FUNCT__ 105 #define __FUNCT__ "PCSetUp_FieldSplit" 106 static PetscErrorCode PCSetUp_FieldSplit(PC pc) 107 { 108 PC_FieldSplit *jac = (PC_FieldSplit*)pc->data; 109 PetscErrorCode ierr; 110 PC_FieldSplitLink ilink; 111 PetscInt i,nsplit; 112 MatStructure flag = pc->flag; 113 114 PetscFunctionBegin; 115 ierr = PCFieldSplitSetDefaults(pc);CHKERRQ(ierr); 116 nsplit = jac->nsplits; 117 ilink = jac->head; 118 119 /* get the matrices for each split */ 120 if (!jac->is) { 121 PetscInt rstart,rend,nslots,bs; 122 123 ierr = MatGetBlockSize(pc->pmat,&bs);CHKERRQ(ierr); 124 ierr = MatGetOwnershipRange(pc->pmat,&rstart,&rend);CHKERRQ(ierr); 125 nslots = (rend - rstart)/bs; 126 ierr = PetscMalloc(nsplit*sizeof(IS),&jac->is);CHKERRQ(ierr); 127 for (i=0; i<nsplit; i++) { 128 if (jac->defaultsplit) { 129 ierr = ISCreateStride(pc->comm,nslots,rstart+i,nsplit,&jac->is[i]);CHKERRQ(ierr); 130 } else { 131 PetscInt *ii,j,k,nfields = ilink->nfields,*fields = ilink->fields; 132 PetscTruth sorted; 133 ierr = PetscMalloc(ilink->nfields*nslots*sizeof(PetscInt),&ii);CHKERRQ(ierr); 134 for (j=0; j<nslots; j++) { 135 for (k=0; k<nfields; k++) { 136 ii[nfields*j + k] = rstart + bs*j + fields[k]; 137 } 138 } 139 ierr = ISCreateGeneral(pc->comm,nslots*nfields,ii,&jac->is[i]);CHKERRQ(ierr); 140 ierr = ISSorted(jac->is[i],&sorted);CHKERRQ(ierr); 141 if (!sorted) SETERRQ(PETSC_ERR_USER,"Fields must be sorted when creating split"); 142 ierr = PetscFree(ii);CHKERRQ(ierr); 143 ilink = ilink->next; 144 } 145 } 146 } 147 148 if (!jac->pmat) { 149 ierr = MatGetSubMatrices(pc->pmat,nsplit,jac->is,jac->is,MAT_INITIAL_MATRIX,&jac->pmat);CHKERRQ(ierr); 150 } else { 151 ierr = MatGetSubMatrices(pc->pmat,nsplit,jac->is,jac->is,MAT_REUSE_MATRIX,&jac->pmat);CHKERRQ(ierr); 152 } 153 154 /* set up the individual PCs */ 155 i = 0; 156 ilink = jac->head; 157 while (ilink) { 158 ierr = KSPSetOperators(ilink->ksp,jac->pmat[i],jac->pmat[i],flag);CHKERRQ(ierr); 159 ierr = KSPSetFromOptions(ilink->ksp);CHKERRQ(ierr); 160 ierr = KSPSetUp(ilink->ksp);CHKERRQ(ierr); 161 i++; 162 ilink = ilink->next; 163 } 164 165 /* create work vectors for each split */ 166 if (!jac->x) { 167 Vec xtmp; 168 ierr = PetscMalloc2(nsplit,Vec,&jac->x,nsplit,Vec,&jac->y);CHKERRQ(ierr); 169 ilink = jac->head; 170 for (i=0; i<nsplit; i++) { 171 Mat A; 172 ierr = KSPGetOperators(ilink->ksp,PETSC_NULL,&A,PETSC_NULL);CHKERRQ(ierr); 173 ierr = MatGetVecs(A,&ilink->x,&ilink->y);CHKERRQ(ierr); 174 jac->x[i] = ilink->x; 175 jac->y[i] = ilink->y; 176 ilink = ilink->next; 177 } 178 /* compute scatter contexts needed by multiplicative versions and non-default splits */ 179 180 ilink = jac->head; 181 ierr = MatGetVecs(pc->pmat,&xtmp,PETSC_NULL);CHKERRQ(ierr); 182 for (i=0; i<nsplit; i++) { 183 ierr = VecScatterCreate(xtmp,jac->is[i],jac->x[i],PETSC_NULL,&ilink->sctx);CHKERRQ(ierr); 184 ilink = ilink->next; 185 } 186 ierr = VecDestroy(xtmp);CHKERRQ(ierr); 187 } 188 PetscFunctionReturn(0); 189 } 190 191 #define FieldSplitSplitSolveAdd(ilink,xx,yy) \ 192 (VecScatterBegin(xx,ilink->x,INSERT_VALUES,SCATTER_FORWARD,ilink->sctx) || \ 193 VecScatterEnd(xx,ilink->x,INSERT_VALUES,SCATTER_FORWARD,ilink->sctx) || \ 194 KSPSolve(ilink->ksp,ilink->x,ilink->y) || \ 195 VecScatterBegin(ilink->y,yy,ADD_VALUES,SCATTER_REVERSE,ilink->sctx) || \ 196 VecScatterEnd(ilink->y,yy,ADD_VALUES,SCATTER_REVERSE,ilink->sctx)) 197 198 #undef __FUNCT__ 199 #define __FUNCT__ "PCApply_FieldSplit" 200 static PetscErrorCode PCApply_FieldSplit(PC pc,Vec x,Vec y) 201 { 202 PC_FieldSplit *jac = (PC_FieldSplit*)pc->data; 203 PetscErrorCode ierr; 204 PC_FieldSplitLink ilink = jac->head; 205 PetscScalar zero = 0.0,mone = -1.0; 206 207 PetscFunctionBegin; 208 if (jac->type == PC_COMPOSITE_ADDITIVE) { 209 if (jac->defaultsplit) { 210 ierr = VecStrideGatherAll(x,jac->x,INSERT_VALUES);CHKERRQ(ierr); 211 while (ilink) { 212 ierr = KSPSolve(ilink->ksp,ilink->x,ilink->y);CHKERRQ(ierr); 213 ilink = ilink->next; 214 } 215 ierr = VecStrideScatterAll(jac->y,y,INSERT_VALUES);CHKERRQ(ierr); 216 } else { 217 PetscInt i = 0; 218 219 ierr = VecSet(y,zero);CHKERRQ(ierr); 220 while (ilink) { 221 ierr = FieldSplitSplitSolveAdd(ilink,x,y);CHKERRQ(ierr); 222 ilink = ilink->next; 223 i++; 224 } 225 } 226 } else { 227 if (!jac->w1) { 228 ierr = VecDuplicate(x,&jac->w1);CHKERRQ(ierr); 229 ierr = VecDuplicate(x,&jac->w2);CHKERRQ(ierr); 230 } 231 ierr = VecSet(y,zero);CHKERRQ(ierr); 232 ierr = FieldSplitSplitSolveAdd(ilink,x,y);CHKERRQ(ierr); 233 while (ilink->next) { 234 ilink = ilink->next; 235 ierr = MatMult(pc->pmat,y,jac->w1);CHKERRQ(ierr); 236 ierr = VecWAXPY(jac->w2,mone,jac->w1,x);CHKERRQ(ierr); 237 ierr = FieldSplitSplitSolveAdd(ilink,jac->w2,y);CHKERRQ(ierr); 238 } 239 } 240 PetscFunctionReturn(0); 241 } 242 243 #undef __FUNCT__ 244 #define __FUNCT__ "PCDestroy_FieldSplit" 245 static PetscErrorCode PCDestroy_FieldSplit(PC pc) 246 { 247 PC_FieldSplit *jac = (PC_FieldSplit*)pc->data; 248 PetscErrorCode ierr; 249 PC_FieldSplitLink ilink = jac->head,next; 250 251 PetscFunctionBegin; 252 while (ilink) { 253 ierr = KSPDestroy(ilink->ksp);CHKERRQ(ierr); 254 if (ilink->x) {ierr = VecDestroy(ilink->x);CHKERRQ(ierr);} 255 if (ilink->y) {ierr = VecDestroy(ilink->y);CHKERRQ(ierr);} 256 if (ilink->sctx) {ierr = VecScatterDestroy(ilink->sctx);CHKERRQ(ierr);} 257 next = ilink->next; 258 ierr = PetscFree2(ilink,ilink->fields);CHKERRQ(ierr); 259 ilink = next; 260 } 261 if (jac->x) {ierr = PetscFree2(jac->x,jac->y);CHKERRQ(ierr);} 262 if (jac->pmat) {ierr = MatDestroyMatrices(jac->nsplits,&jac->pmat);CHKERRQ(ierr);} 263 if (jac->is) { 264 PetscInt i; 265 for (i=0; i<jac->nsplits; i++) {ierr = ISDestroy(jac->is[i]);CHKERRQ(ierr);} 266 ierr = PetscFree(jac->is);CHKERRQ(ierr); 267 } 268 if (jac->w1) {ierr = VecDestroy(jac->w1);CHKERRQ(ierr);} 269 if (jac->w2) {ierr = VecDestroy(jac->w2);CHKERRQ(ierr);} 270 ierr = PetscFree(jac);CHKERRQ(ierr); 271 PetscFunctionReturn(0); 272 } 273 274 #undef __FUNCT__ 275 #define __FUNCT__ "PCSetFromOptions_FieldSplit" 276 static PetscErrorCode PCSetFromOptions_FieldSplit(PC pc) 277 /* This does not call KSPSetFromOptions() on the subksp's, see PCSetFromOptionsBJacobi/ASM() */ 278 { 279 PetscErrorCode ierr; 280 PetscInt i = 0,nfields,fields[12]; 281 PetscTruth flg; 282 char optionname[128]; 283 PC_FieldSplit *jac = (PC_FieldSplit*)pc->data; 284 285 PetscFunctionBegin; 286 ierr = PetscOptionsHead("FieldSplit options");CHKERRQ(ierr); 287 ierr = PetscOptionsEnum("-pc_fieldsplit_type","Type of composition","PCFieldSplitSetType",PCCompositeTypes,(PetscEnum)jac->type,(PetscEnum*)&jac->type,&flg);CHKERRQ(ierr); 288 while (PETSC_TRUE) { 289 sprintf(optionname,"-pc_fieldsplit_%d_fields",(int)i++); 290 nfields = 12; 291 ierr = PetscOptionsIntArray(optionname,"Fields in this split","PCFieldSplitSetFields",fields,&nfields,&flg);CHKERRQ(ierr); 292 if (!flg) break; 293 if (!nfields) SETERRQ(PETSC_ERR_USER,"Cannot list zero fields"); 294 ierr = PCFieldSplitSetFields(pc,nfields,fields);CHKERRQ(ierr); 295 } 296 ierr = PetscOptionsTail();CHKERRQ(ierr); 297 PetscFunctionReturn(0); 298 } 299 300 /*------------------------------------------------------------------------------------*/ 301 302 EXTERN_C_BEGIN 303 #undef __FUNCT__ 304 #define __FUNCT__ "PCFieldSplitSetFields_FieldSplit" 305 PetscErrorCode PETSCKSP_DLLEXPORT PCFieldSplitSetFields_FieldSplit(PC pc,PetscInt n,PetscInt *fields) 306 { 307 PC_FieldSplit *jac = (PC_FieldSplit*)pc->data; 308 PetscErrorCode ierr; 309 PC_FieldSplitLink ilink,next = jac->head; 310 char prefix[128]; 311 312 PetscFunctionBegin; 313 if (n <= 0) SETERRQ(PETSC_ERR_ARG_OUTOFRANGE,"Negative number of fields requested"); 314 ierr = PetscMalloc2(1,struct _PC_FieldSplitLink,&ilink,n,PetscInt,&ilink->fields);CHKERRQ(ierr); 315 ierr = PetscMemcpy(ilink->fields,fields,n*sizeof(PetscInt));CHKERRQ(ierr); 316 ilink->nfields = n; 317 ilink->next = PETSC_NULL; 318 ierr = KSPCreate(pc->comm,&ilink->ksp);CHKERRQ(ierr); 319 ierr = KSPSetType(ilink->ksp,KSPPREONLY);CHKERRQ(ierr); 320 321 if (pc->prefix) { 322 sprintf(prefix,"%sfieldsplit_%d_",pc->prefix,(int)jac->nsplits); 323 } else { 324 sprintf(prefix,"fieldsplit_%d_",(int)jac->nsplits); 325 } 326 ierr = KSPSetOptionsPrefix(ilink->ksp,prefix);CHKERRQ(ierr); 327 328 if (!next) { 329 jac->head = ilink; 330 } else { 331 while (next->next) { 332 next = next->next; 333 } 334 next->next = ilink; 335 } 336 jac->nsplits++; 337 PetscFunctionReturn(0); 338 } 339 EXTERN_C_END 340 341 342 EXTERN_C_BEGIN 343 #undef __FUNCT__ 344 #define __FUNCT__ "PCFieldSplitGetSubKSP_FieldSplit" 345 PetscErrorCode PETSCKSP_DLLEXPORT PCFieldSplitGetSubKSP_FieldSplit(PC pc,PetscInt *n,KSP **subksp) 346 { 347 PC_FieldSplit *jac = (PC_FieldSplit*)pc->data; 348 PetscErrorCode ierr; 349 PetscInt cnt = 0; 350 PC_FieldSplitLink ilink = jac->head; 351 352 PetscFunctionBegin; 353 ierr = PetscMalloc(jac->nsplits*sizeof(KSP*),subksp);CHKERRQ(ierr); 354 while (ilink) { 355 (*subksp)[cnt++] = ilink->ksp; 356 ilink = ilink->next; 357 } 358 if (cnt != jac->nsplits) SETERRQ2(PETSC_ERR_PLIB,"Corrupt PCFIELDSPLIT object: number splits in linked list %D in object %D",cnt,jac->nsplits); 359 *n = jac->nsplits; 360 PetscFunctionReturn(0); 361 } 362 EXTERN_C_END 363 364 #undef __FUNCT__ 365 #define __FUNCT__ "PCFieldSplitSetFields" 366 /*@ 367 PCFieldSplitSetFields - Sets the fields for one particular split in the field split preconditioner 368 369 Collective on PC 370 371 Input Parameters: 372 + pc - the preconditioner context 373 . n - the number of fields in this split 374 . fields - the fields in this split 375 376 Level: intermediate 377 378 .seealso: PCFieldSplitGetSubKSP(), PCFIELDSPLIT 379 380 @*/ 381 PetscErrorCode PETSCKSP_DLLEXPORT PCFieldSplitSetFields(PC pc,PetscInt n, PetscInt *fields) 382 { 383 PetscErrorCode ierr,(*f)(PC,PetscInt,PetscInt *); 384 385 PetscFunctionBegin; 386 PetscValidHeaderSpecific(pc,PC_COOKIE,1); 387 ierr = PetscObjectQueryFunction((PetscObject)pc,"PCFieldSplitSetFields_C",(void (**)(void))&f);CHKERRQ(ierr); 388 if (f) { 389 ierr = (*f)(pc,n,fields);CHKERRQ(ierr); 390 } 391 PetscFunctionReturn(0); 392 } 393 394 #undef __FUNCT__ 395 #define __FUNCT__ "PCFieldSplitGetSubKSP" 396 /*@C 397 PCFieldSplitGetSubKSP - Gets the KSP contexts for all splits 398 399 Collective on KSP 400 401 Input Parameter: 402 . pc - the preconditioner context 403 404 Output Parameters: 405 + n - the number of split 406 - pc - the array of KSP contexts 407 408 Note: 409 After PCFieldSplitGetSubKSP() the array of KSPs IS to be freed 410 411 You must call KSPSetUp() before calling PCFieldSplitGetSubKSP(). 412 413 Level: advanced 414 415 .seealso: PCFIELDSPLIT 416 @*/ 417 PetscErrorCode PETSCKSP_DLLEXPORT PCFieldSplitGetSubKSP(PC pc,PetscInt *n,KSP *subksp[]) 418 { 419 PetscErrorCode ierr,(*f)(PC,PetscInt*,KSP **); 420 421 PetscFunctionBegin; 422 PetscValidHeaderSpecific(pc,PC_COOKIE,1); 423 PetscValidIntPointer(n,2); 424 ierr = PetscObjectQueryFunction((PetscObject)pc,"PCFieldSplitGetSubKSP_C",(void (**)(void))&f);CHKERRQ(ierr); 425 if (f) { 426 ierr = (*f)(pc,n,subksp);CHKERRQ(ierr); 427 } else { 428 SETERRQ(PETSC_ERR_ARG_WRONG,"Cannot get subksp for this type of PC"); 429 } 430 PetscFunctionReturn(0); 431 } 432 433 EXTERN_C_BEGIN 434 #undef __FUNCT__ 435 #define __FUNCT__ "PCFieldSplitSetType_FieldSplit" 436 PetscErrorCode PETSCKSP_DLLEXPORT PCFieldSplitSetType_FieldSplit(PC pc,PCCompositeType type) 437 { 438 PC_FieldSplit *jac = (PC_FieldSplit*)pc->data; 439 440 PetscFunctionBegin; 441 jac->type = type; 442 PetscFunctionReturn(0); 443 } 444 EXTERN_C_END 445 446 #undef __FUNCT__ 447 #define __FUNCT__ "PCFieldSplitSetType" 448 /*@C 449 PCFieldSplitSetType - Sets the type of fieldsplit preconditioner. 450 451 Collective on PC 452 453 Input Parameter: 454 . pc - the preconditioner context 455 . type - PC_COMPOSITE_ADDITIVE (default), PC_COMPOSITE_MULTIPLICATIVE 456 457 Options Database Key: 458 . -pc_fieldsplit_type <type: one of multiplicative, additive, special> - Sets fieldsplit preconditioner type 459 460 Level: Developer 461 462 .keywords: PC, set, type, composite preconditioner, additive, multiplicative 463 464 .seealso: PCCompositeSetType() 465 466 @*/ 467 PetscErrorCode PETSCKSP_DLLEXPORT PCFieldSplitSetType(PC pc,PCCompositeType type) 468 { 469 PetscErrorCode ierr,(*f)(PC,PCCompositeType); 470 471 PetscFunctionBegin; 472 PetscValidHeaderSpecific(pc,PC_COOKIE,1); 473 ierr = PetscObjectQueryFunction((PetscObject)pc,"PCFieldSplitSetType_C",(void (**)(void))&f);CHKERRQ(ierr); 474 if (f) { 475 ierr = (*f)(pc,type);CHKERRQ(ierr); 476 } 477 PetscFunctionReturn(0); 478 } 479 480 /* -------------------------------------------------------------------------------------*/ 481 /*MC 482 PCFIELDSPLIT - Preconditioner created by combining seperate preconditioners for individual 483 fields or groups of fields 484 485 486 To set options on the solvers for each block append -sub_ to all the PC 487 options database keys. For example, -sub_pc_type ilu -sub_pc_ilu_levels 1 488 489 To set the options on the solvers seperate for each block call PCFieldSplitGetSubKSP() 490 and set the options directly on the resulting KSP object 491 492 Level: intermediate 493 494 Options Database Keys: 495 + -pc_splitfield_%d_fields <a,b,..> - indicates the fields to be used in the %d'th split 496 . -pc_splitfield_default - automatically add any fields to additional splits that have not 497 been supplied explicitly by -pc_splitfield_%d_fields 498 - -pc_splitfield_type <additive,multiplicative> 499 500 Concepts: physics based preconditioners 501 502 .seealso: PCCreate(), PCSetType(), PCType (for list of available types), PC, 503 PCFieldSplitGetSubKSP(), PCFieldSplitSetFields(),PCFieldSplitSetType() 504 M*/ 505 506 EXTERN_C_BEGIN 507 #undef __FUNCT__ 508 #define __FUNCT__ "PCCreate_FieldSplit" 509 PetscErrorCode PETSCKSP_DLLEXPORT PCCreate_FieldSplit(PC pc) 510 { 511 PetscErrorCode ierr; 512 PC_FieldSplit *jac; 513 514 PetscFunctionBegin; 515 ierr = PetscNew(PC_FieldSplit,&jac);CHKERRQ(ierr); 516 ierr = PetscLogObjectMemory(pc,sizeof(PC_FieldSplit));CHKERRQ(ierr); 517 jac->bs = -1; 518 jac->nsplits = 0; 519 jac->type = PC_COMPOSITE_ADDITIVE; 520 pc->data = (void*)jac; 521 522 pc->ops->apply = PCApply_FieldSplit; 523 pc->ops->setup = PCSetUp_FieldSplit; 524 pc->ops->destroy = PCDestroy_FieldSplit; 525 pc->ops->setfromoptions = PCSetFromOptions_FieldSplit; 526 pc->ops->view = PCView_FieldSplit; 527 pc->ops->applyrichardson = 0; 528 529 ierr = PetscObjectComposeFunctionDynamic((PetscObject)pc,"PCFieldSplitGetSubKSP_C","PCFieldSplitGetSubKSP_FieldSplit", 530 PCFieldSplitGetSubKSP_FieldSplit);CHKERRQ(ierr); 531 ierr = PetscObjectComposeFunctionDynamic((PetscObject)pc,"PCFieldSplitSetFields_C","PCFieldSplitSetFields_FieldSplit", 532 PCFieldSplitSetFields_FieldSplit);CHKERRQ(ierr); 533 ierr = PetscObjectComposeFunctionDynamic((PetscObject)pc,"PCFieldSplitSetType_C","PCFieldSplitSetType_FieldSplit", 534 PCFieldSplitSetType_FieldSplit);CHKERRQ(ierr); 535 PetscFunctionReturn(0); 536 } 537 EXTERN_C_END 538 539 540