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 63 PetscCall(PetscFunctionListDestroy(&((PetscObject)pc)->qlist)); 64 /* Reinitialize function pointers in PCOps structure */ 65 PetscCall(PetscMemzero(pc->ops, sizeof(struct _PCOps))); 66 /* XXX Is this OK?? */ 67 pc->modifysubmatrices = NULL; 68 pc->modifysubmatricesP = NULL; 69 /* Call the PCCreate_XXX routine for this particular preconditioner */ 70 pc->setupcalled = PETSC_FALSE; 71 72 PetscCall(PetscObjectChangeTypeName((PetscObject)pc, type)); 73 PetscCall((*r)(pc)); 74 PetscFunctionReturn(PETSC_SUCCESS); 75 } 76 77 /*@ 78 PCGetType - Gets the `PCType` (as a string) from the `PC` 79 context. 80 81 Not Collective 82 83 Input Parameter: 84 . pc - the preconditioner context 85 86 Output Parameter: 87 . type - name of preconditioner method 88 89 Level: intermediate 90 91 .seealso: [](ch_ksp), `PC`, `PCType`, `PCSetType()` 92 @*/ 93 PetscErrorCode PCGetType(PC pc, PCType *type) 94 { 95 PetscFunctionBegin; 96 PetscValidHeaderSpecific(pc, PC_CLASSID, 1); 97 PetscAssertPointer(type, 2); 98 *type = ((PetscObject)pc)->type_name; 99 PetscFunctionReturn(PETSC_SUCCESS); 100 } 101 102 PETSC_INTERN PetscErrorCode PCGetDefaultType_Private(PC, const char *[]); 103 104 /*@ 105 PCSetFromOptions - Sets `PC` options from the options database. 106 107 Collective 108 109 Input Parameter: 110 . pc - the preconditioner context 111 112 Options Database Key: 113 . -pc_type - name of type, for example `bjacobi` 114 115 Level: advanced 116 117 Notes: 118 This routine must be called before `PCSetUp()` if the user is to be 119 allowed to set the preconditioner method from the options database. 120 121 This is called from `KSPSetFromOptions()` so rarely needs to be called directly 122 123 .seealso: [](ch_ksp), `PC`, `PCSetType()`, `PCType`, `KSPSetFromOptions()` 124 @*/ 125 PetscErrorCode PCSetFromOptions(PC pc) 126 { 127 char type[256]; 128 const char *def; 129 PetscBool flg; 130 131 PetscFunctionBegin; 132 PetscValidHeaderSpecific(pc, PC_CLASSID, 1); 133 134 PetscCall(PCRegisterAll()); 135 if (!((PetscObject)pc)->type_name) { 136 PetscCall(PCGetDefaultType_Private(pc, &def)); 137 } else { 138 def = ((PetscObject)pc)->type_name; 139 } 140 PetscObjectOptionsBegin((PetscObject)pc); 141 142 PetscCall(PetscOptionsFList("-pc_type", "Preconditioner", "PCSetType", PCList, def, type, 256, &flg)); 143 if (flg) { 144 PetscCall(PCSetType(pc, type)); 145 } else if (!((PetscObject)pc)->type_name && def) { 146 PetscCall(PCSetType(pc, def)); 147 } 148 149 PetscCall(PetscObjectTypeCompare((PetscObject)pc, PCNONE, &flg)); 150 if (flg) goto skipoptions; 151 152 PetscCall(PetscOptionsBool("-pc_use_amat", "use Amat (instead of Pmat) to define preconditioner in nested inner solves", "PCSetUseAmat", pc->useAmat, &pc->useAmat, NULL)); 153 154 PetscTryTypeMethod(pc, setfromoptions, PetscOptionsObject); 155 156 skipoptions: 157 /* process any options handlers added with PetscObjectAddOptionsHandler() */ 158 PetscCall(PetscObjectProcessOptionsHandlers((PetscObject)pc, PetscOptionsObject)); 159 PetscOptionsEnd(); 160 pc->setfromoptionscalled++; 161 PetscFunctionReturn(PETSC_SUCCESS); 162 } 163 164 /*@ 165 PCSetDM - Sets the `DM` that may be used by some preconditioners 166 167 Logically Collective 168 169 Input Parameters: 170 + pc - the preconditioner context 171 - dm - the `DM`, can be `NULL` to remove any current `DM` 172 173 Level: intermediate 174 175 Note: 176 Users generally call `KSPSetDM()`, `SNESSetDM()`, or `TSSetDM()` so this is rarely called directly 177 178 Developer Notes: 179 The routines KSP/SNES/TSSetDM() require `dm` to be non-`NULL`, but this one can be `NULL` since all it does is 180 replace the current `DM` 181 182 .seealso: [](ch_ksp), `PC`, `DM`, `PCGetDM()`, `KSPSetDM()`, `KSPGetDM()`, `SNESSetDM()`, `TSSetDM()` 183 @*/ 184 PetscErrorCode PCSetDM(PC pc, DM dm) 185 { 186 PetscFunctionBegin; 187 PetscValidHeaderSpecific(pc, PC_CLASSID, 1); 188 if (dm) PetscCall(PetscObjectReference((PetscObject)dm)); 189 PetscCall(DMDestroy(&pc->dm)); 190 pc->dm = dm; 191 PetscFunctionReturn(PETSC_SUCCESS); 192 } 193 194 /*@ 195 PCGetDM - Gets the `DM` that may be used by some preconditioners 196 197 Not Collective 198 199 Input Parameter: 200 . pc - the preconditioner context 201 202 Output Parameter: 203 . dm - the `DM` 204 205 Level: intermediate 206 207 .seealso: [](ch_ksp), `PC`, `DM`, `PCSetDM()`, `KSPSetDM()`, `KSPGetDM()` 208 @*/ 209 PetscErrorCode PCGetDM(PC pc, DM *dm) 210 { 211 PetscFunctionBegin; 212 PetscValidHeaderSpecific(pc, PC_CLASSID, 1); 213 *dm = pc->dm; 214 PetscFunctionReturn(PETSC_SUCCESS); 215 } 216 217 /*@ 218 PCSetApplicationContext - Sets the optional user-defined context for the preconditioner 219 220 Logically Collective 221 222 Input Parameters: 223 + pc - the `PC` context 224 - ctx - optional user context 225 226 Level: advanced 227 228 Fortran Note: 229 This only works when `ctx` is a Fortran derived type (it cannot be a `PetscObject`), we recommend writing a Fortran interface definition for this 230 function that tells the Fortran compiler the derived data type that is passed in as the `ctx` argument. See `PCGetApplicationContext()` for 231 an example. 232 233 .seealso: [](ch_ksp), `PC`, `PCGetApplicationContext()`, `KSPSetApplicationContext()`, `KSPGetApplicationContext()`, `PetscObjectCompose()` 234 @*/ 235 PetscErrorCode PCSetApplicationContext(PC pc, PetscCtx ctx) 236 { 237 PetscFunctionBegin; 238 PetscValidHeaderSpecific(pc, PC_CLASSID, 1); 239 pc->ctx = ctx; 240 PetscFunctionReturn(PETSC_SUCCESS); 241 } 242 243 /*@ 244 PCGetApplicationContext - Gets the user-defined context for the preconditioner set with `PCSetApplicationContext()` 245 246 Not Collective 247 248 Input Parameter: 249 . pc - `PC` context 250 251 Output Parameter: 252 . ctx - user context 253 254 Level: intermediate 255 256 Fortran Note: 257 This only works when the context is a Fortran derived type or a `PetscObject`. Define `ctx` with 258 .vb 259 type(tUsertype), pointer :: ctx 260 .ve 261 262 .seealso: [](ch_ksp), `PC`, `PCSetApplicationContext()`, `KSPSetApplicationContext()`, `KSPGetApplicationContext()` 263 @*/ 264 PetscErrorCode PCGetApplicationContext(PC pc, PetscCtxRt ctx) 265 { 266 PetscFunctionBegin; 267 PetscValidHeaderSpecific(pc, PC_CLASSID, 1); 268 *(void **)ctx = pc->ctx; 269 PetscFunctionReturn(PETSC_SUCCESS); 270 } 271