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