1 /* 2 Routines to set PC methods and options. 3 */ 4 5 #include <petsc/private/pcimpl.h> /*I "petscpc.h" I*/ 6 #include <petscdm.h> 7 8 PetscBool PCRegisterAllCalled = PETSC_FALSE; 9 /* 10 Contains the list of registered PC routines 11 */ 12 PetscFunctionList PCList = NULL; 13 14 /*@ 15 PCSetType - Builds `PC` for a particular preconditioner type 16 17 Collective 18 19 Input Parameters: 20 + pc - the preconditioner context 21 - type - a known method, see `PCType` for possible values 22 23 Options Database Key: 24 . -pc_type <type> - Sets `PC` type 25 26 Notes: 27 Normally, it is best to use the `KSPSetFromOptions()` command and 28 then set the `PC` type from the options database rather than by using 29 this routine. Using the options database provides the user with 30 maximum flexibility in evaluating the many different preconditioners. 31 The `PCSetType()` routine is provided for those situations where it 32 is necessary to set the preconditioner independently of the command 33 line or options database. This might be the case, for example, when 34 the choice of preconditioner changes during the execution of the 35 program, and the user's application is taking responsibility for 36 choosing the appropriate preconditioner. 37 38 Level: intermediate 39 40 Developer Notes: 41 `PCRegister()` is used to add preconditioner types to `PCList` from which they 42 are accessed by `PCSetType()`. 43 44 .seealso: [](ch_ksp), `KSPSetType()`, `PCType`, `PCRegister()`, `PCCreate()`, `KSPGetPC()` 45 @*/ 46 PetscErrorCode PCSetType(PC pc, PCType type) 47 { 48 PetscBool match; 49 PetscErrorCode (*r)(PC); 50 51 PetscFunctionBegin; 52 PetscValidHeaderSpecific(pc, PC_CLASSID, 1); 53 PetscAssertPointer(type, 2); 54 55 PetscCall(PetscObjectTypeCompare((PetscObject)pc, type, &match)); 56 if (match) PetscFunctionReturn(PETSC_SUCCESS); 57 58 PetscCall(PetscFunctionListFind(PCList, type, &r)); 59 PetscCheck(r, PetscObjectComm((PetscObject)pc), PETSC_ERR_ARG_UNKNOWN_TYPE, "Unable to find requested PC type %s", type); 60 /* Destroy the previous private PC context */ 61 PetscTryTypeMethod(pc, destroy); 62 pc->ops->destroy = NULL; 63 pc->data = NULL; 64 65 PetscCall(PetscFunctionListDestroy(&((PetscObject)pc)->qlist)); 66 /* Reinitialize function pointers in PCOps structure */ 67 PetscCall(PetscMemzero(pc->ops, sizeof(struct _PCOps))); 68 /* XXX Is this OK?? */ 69 pc->modifysubmatrices = NULL; 70 pc->modifysubmatricesP = NULL; 71 /* Call the PCCreate_XXX routine for this particular preconditioner */ 72 pc->setupcalled = 0; 73 74 PetscCall(PetscObjectChangeTypeName((PetscObject)pc, type)); 75 PetscCall((*r)(pc)); 76 PetscFunctionReturn(PETSC_SUCCESS); 77 } 78 79 /*@ 80 PCGetType - Gets the `PCType` (as a string) from the `PC` 81 context. 82 83 Not Collective 84 85 Input Parameter: 86 . pc - the preconditioner context 87 88 Output Parameter: 89 . type - name of preconditioner method 90 91 Level: intermediate 92 93 .seealso: [](ch_ksp), `PC`, `PCType`, `PCSetType()` 94 @*/ 95 PetscErrorCode PCGetType(PC pc, PCType *type) 96 { 97 PetscFunctionBegin; 98 PetscValidHeaderSpecific(pc, PC_CLASSID, 1); 99 PetscAssertPointer(type, 2); 100 *type = ((PetscObject)pc)->type_name; 101 PetscFunctionReturn(PETSC_SUCCESS); 102 } 103 104 PETSC_INTERN PetscErrorCode PCGetDefaultType_Private(PC, const char *[]); 105 106 /*@ 107 PCSetFromOptions - Sets `PC` options from the options database. 108 109 Collective 110 111 Input Parameter: 112 . pc - the preconditioner context 113 114 Options Database Key: 115 . -pc_type - name of type, for example `bjacobi` 116 117 Level: advanced 118 119 Notes: 120 This routine must be called before `PCSetUp()` if the user is to be 121 allowed to set the preconditioner method from the options database. 122 123 This is called from `KSPSetFromOptions()` so rarely needs to be called directly 124 125 .seealso: [](ch_ksp), `PC`, `PCSetType()`, `PCType`, `KSPSetFromOptions()` 126 @*/ 127 PetscErrorCode PCSetFromOptions(PC pc) 128 { 129 char type[256]; 130 const char *def; 131 PetscBool flg; 132 133 PetscFunctionBegin; 134 PetscValidHeaderSpecific(pc, PC_CLASSID, 1); 135 136 PetscCall(PCRegisterAll()); 137 if (!((PetscObject)pc)->type_name) { 138 PetscCall(PCGetDefaultType_Private(pc, &def)); 139 } else { 140 def = ((PetscObject)pc)->type_name; 141 } 142 PetscObjectOptionsBegin((PetscObject)pc); 143 144 PetscCall(PetscOptionsFList("-pc_type", "Preconditioner", "PCSetType", PCList, def, type, 256, &flg)); 145 if (flg) { 146 PetscCall(PCSetType(pc, type)); 147 } else if (!((PetscObject)pc)->type_name && def) { 148 PetscCall(PCSetType(pc, def)); 149 } 150 151 PetscCall(PetscObjectTypeCompare((PetscObject)pc, PCNONE, &flg)); 152 if (flg) goto skipoptions; 153 154 PetscCall(PetscOptionsBool("-pc_use_amat", "use Amat (instead of Pmat) to define preconditioner in nested inner solves", "PCSetUseAmat", pc->useAmat, &pc->useAmat, NULL)); 155 156 PetscTryTypeMethod(pc, setfromoptions, PetscOptionsObject); 157 158 skipoptions: 159 /* process any options handlers added with PetscObjectAddOptionsHandler() */ 160 PetscCall(PetscObjectProcessOptionsHandlers((PetscObject)pc, PetscOptionsObject)); 161 PetscOptionsEnd(); 162 pc->setfromoptionscalled++; 163 PetscFunctionReturn(PETSC_SUCCESS); 164 } 165 166 /*@ 167 PCSetDM - Sets the `DM` that may be used by some preconditioners 168 169 Logically Collective 170 171 Input Parameters: 172 + pc - the preconditioner context 173 - dm - the `DM`, can be `NULL` to remove any current `DM` 174 175 Level: intermediate 176 177 Note: 178 Users generally call `KSPSetDM()`, `SNESSetDM()`, or `TSSetDM()` so this is rarely called directly 179 180 Developer Notes: 181 The routines KSP/SNES/TSSetDM() require `dm` to be non-`NULL`, but this one can be `NULL` since all it does is 182 replace the current `DM` 183 184 .seealso: [](ch_ksp), `PC`, `DM`, `PCGetDM()`, `KSPSetDM()`, `KSPGetDM()`, `SNESSetDM()`, `TSSetDM()` 185 @*/ 186 PetscErrorCode PCSetDM(PC pc, DM dm) 187 { 188 PetscFunctionBegin; 189 PetscValidHeaderSpecific(pc, PC_CLASSID, 1); 190 if (dm) PetscCall(PetscObjectReference((PetscObject)dm)); 191 PetscCall(DMDestroy(&pc->dm)); 192 pc->dm = dm; 193 PetscFunctionReturn(PETSC_SUCCESS); 194 } 195 196 /*@ 197 PCGetDM - Gets the `DM` that may be used by some preconditioners 198 199 Not Collective 200 201 Input Parameter: 202 . pc - the preconditioner context 203 204 Output Parameter: 205 . dm - the `DM` 206 207 Level: intermediate 208 209 .seealso: [](ch_ksp), `PC`, `DM`, `PCSetDM()`, `KSPSetDM()`, `KSPGetDM()` 210 @*/ 211 PetscErrorCode PCGetDM(PC pc, DM *dm) 212 { 213 PetscFunctionBegin; 214 PetscValidHeaderSpecific(pc, PC_CLASSID, 1); 215 *dm = pc->dm; 216 PetscFunctionReturn(PETSC_SUCCESS); 217 } 218 219 /*@ 220 PCSetApplicationContext - Sets the optional user-defined context for the preconditioner 221 222 Logically Collective 223 224 Input Parameters: 225 + pc - the `PC` context 226 - ctx - optional user context 227 228 Level: advanced 229 230 Fortran Note: 231 This only works when `ctx` is a Fortran derived type (it cannot be a `PetscObject`), we recommend writing a Fortran interface definition for this 232 function that tells the Fortran compiler the derived data type that is passed in as the `ctx` argument. See `PCGetApplicationContext()` for 233 an example. 234 235 .seealso: [](ch_ksp), `PC`, `PCGetApplicationContext()`, `KSPSetApplicationContext()`, `KSPGetApplicationContext()`, `PetscObjectCompose()` 236 @*/ 237 PetscErrorCode PCSetApplicationContext(PC pc, void *ctx) 238 { 239 PetscFunctionBegin; 240 PetscValidHeaderSpecific(pc, PC_CLASSID, 1); 241 pc->ctx = ctx; 242 PetscFunctionReturn(PETSC_SUCCESS); 243 } 244 245 /*@ 246 PCGetApplicationContext - Gets the user-defined context for the preconditioner set with `PCSetApplicationContext()` 247 248 Not Collective 249 250 Input Parameter: 251 . pc - `PC` context 252 253 Output Parameter: 254 . ctx - user context 255 256 Level: intermediate 257 258 Fortran Notes: 259 This only works when the context is a Fortran derived type (it cannot be a `PetscObject`) and you **must** write a Fortran interface definition for this 260 function that tells the Fortran compiler the derived data type that is returned as the `ctx` argument. For example, 261 .vb 262 Interface PCGetApplicationContext 263 Subroutine PCGetApplicationContext(pc,ctx,ierr) 264 #include <petsc/finclude/petscpc.h> 265 use petscpc 266 PC pc 267 type(tUsertype), pointer :: ctx 268 PetscErrorCode ierr 269 End Subroutine 270 End Interface PCGetApplicationContext 271 .ve 272 273 The prototpye for `ctx` must be 274 .vb 275 type(tUsertype), pointer :: ctx 276 .ve 277 278 .seealso: [](ch_ksp), `PC`, `PCSetApplicationContext()`, `KSPSetApplicationContext()`, `KSPGetApplicationContext()` 279 @*/ 280 PetscErrorCode PCGetApplicationContext(PC pc, PeCtx ctx) 281 { 282 PetscFunctionBegin; 283 PetscValidHeaderSpecific(pc, PC_CLASSID, 1); 284 *(void **)ctx = pc->ctx; 285 PetscFunctionReturn(PETSC_SUCCESS); 286 } 287