1 /*$Id: pcset.c,v 1.118 2001/08/21 21:03:13 bsmith Exp $*/ 2 /* 3 Routines to set PC methods and options. 4 */ 5 6 #include "src/ksp/pc/pcimpl.h" /*I "petscpc.h" I*/ 7 #include "petscsys.h" 8 9 PetscTruth PCRegisterAllCalled = PETSC_FALSE; 10 /* 11 Contains the list of registered KSP routines 12 */ 13 PetscFList PCList = 0; 14 15 #undef __FUNCT__ 16 #define __FUNCT__ "PCSetType" 17 /*@C 18 PCSetType - Builds PC for a particular preconditioner. 19 20 Collective on PC 21 22 Input Parameter: 23 + pc - the preconditioner context. 24 - type - a known method 25 26 Options Database Key: 27 . -pc_type <type> - Sets PC type 28 29 Use -help for a list of available methods (for instance, 30 jacobi or bjacobi) 31 32 Notes: 33 See "petsc/include/petscpc.h" for available methods (for instance, 34 PCJACOBI, PCILU, or PCBJACOBI). 35 36 Normally, it is best to use the KSPSetFromOptions() command and 37 then set the PC type from the options database rather than by using 38 this routine. Using the options database provides the user with 39 maximum flexibility in evaluating the many different preconditioners. 40 The PCSetType() routine is provided for those situations where it 41 is necessary to set the preconditioner independently of the command 42 line or options database. This might be the case, for example, when 43 the choice of preconditioner changes during the execution of the 44 program, and the user's application is taking responsibility for 45 choosing the appropriate preconditioner. In other words, this 46 routine is not for beginners. 47 48 Level: intermediate 49 50 .keywords: PC, set, method, type 51 52 .seealso: KSPSetType(), PCType 53 54 @*/ 55 int PCSetType(PC pc,const PCType type) 56 { 57 int ierr,(*r)(PC); 58 PetscTruth match; 59 60 PetscFunctionBegin; 61 PetscValidHeaderSpecific(pc,PC_COOKIE); 62 PetscValidCharPointer(type); 63 64 ierr = PetscTypeCompare((PetscObject)pc,type,&match);CHKERRQ(ierr); 65 if (match) PetscFunctionReturn(0); 66 67 if (pc->ops->destroy) {ierr = (*pc->ops->destroy)(pc);CHKERRQ(ierr);} 68 ierr = PetscFListDestroy(&pc->qlist);CHKERRQ(ierr); 69 pc->data = 0; 70 pc->setupcalled = 0; 71 72 /* Get the function pointers for the method requested */ 73 if (!PCRegisterAllCalled) {ierr = PCRegisterAll(0);CHKERRQ(ierr);} 74 75 /* Determine the PCCreateXXX routine for a particular preconditioner */ 76 ierr = PetscFListFind(pc->comm,PCList,type,(void (**)(void)) &r);CHKERRQ(ierr); 77 if (!r) SETERRQ1(1,"Unable to find requested PC type %s",type); 78 if (pc->data) {ierr = PetscFree(pc->data);CHKERRQ(ierr);} 79 80 pc->ops->destroy = (int (*)(PC)) 0; 81 pc->ops->view = (int (*)(PC,PetscViewer)) 0; 82 pc->ops->apply = (int (*)(PC,Vec,Vec)) 0; 83 pc->ops->setup = (int (*)(PC)) 0; 84 pc->ops->applyrichardson = (int (*)(PC,Vec,Vec,Vec,PetscReal,PetscReal,PetscReal,int)) 0; 85 pc->ops->applyBA = (int (*)(PC,int,Vec,Vec,Vec)) 0; 86 pc->ops->setfromoptions = (int (*)(PC)) 0; 87 pc->ops->applytranspose = (int (*)(PC,Vec,Vec)) 0; 88 pc->ops->applyBAtranspose = (int (*)(PC,int,Vec,Vec,Vec)) 0; 89 pc->ops->presolve = (int (*)(PC,KSP,Vec,Vec)) 0; 90 pc->ops->postsolve = (int (*)(PC,KSP,Vec,Vec)) 0; 91 pc->ops->getfactoredmatrix = (int (*)(PC,Mat*)) 0; 92 pc->ops->applysymmetricleft = (int (*)(PC,Vec,Vec)) 0; 93 pc->ops->applysymmetricright = (int (*)(PC,Vec,Vec)) 0; 94 pc->ops->setuponblocks = (int (*)(PC)) 0; 95 pc->modifysubmatrices = (int (*)(PC,int,const IS[],const IS[],Mat[],void*)) 0; 96 97 /* Call the PCCreateXXX routine for this particular preconditioner */ 98 ierr = (*r)(pc);CHKERRQ(ierr); 99 100 ierr = PetscObjectChangeTypeName((PetscObject)pc,type);CHKERRQ(ierr); 101 PetscFunctionReturn(0); 102 } 103 104 #undef __FUNCT__ 105 #define __FUNCT__ "PCRegisterDestroy" 106 /*@C 107 PCRegisterDestroy - Frees the list of preconditioners that were 108 registered by PCRegisterDynamic(). 109 110 Not Collective 111 112 Level: advanced 113 114 .keywords: PC, register, destroy 115 116 .seealso: PCRegisterAll(), PCRegisterAll() 117 118 @*/ 119 int PCRegisterDestroy(void) 120 { 121 int ierr; 122 123 PetscFunctionBegin; 124 if (PCList) { 125 ierr = PetscFListDestroy(&PCList);CHKERRQ(ierr); 126 PCList = 0; 127 } 128 PCRegisterAllCalled = PETSC_FALSE; 129 PetscFunctionReturn(0); 130 } 131 132 #undef __FUNCT__ 133 #define __FUNCT__ "PCGetType" 134 /*@C 135 PCGetType - Gets the PC method type and name (as a string) from the PC 136 context. 137 138 Not Collective 139 140 Input Parameter: 141 . pc - the preconditioner context 142 143 Output Parameter: 144 . name - name of preconditioner 145 146 Level: intermediate 147 148 .keywords: PC, get, method, name, type 149 150 .seealso: PCSetType() 151 152 @*/ 153 int PCGetType(PC pc,PCType *meth) 154 { 155 PetscFunctionBegin; 156 *meth = (PCType) pc->type_name; 157 PetscFunctionReturn(0); 158 } 159 160 #undef __FUNCT__ 161 #define __FUNCT__ "PCSetFromOptions" 162 /*@ 163 PCSetFromOptions - Sets PC options from the options database. 164 This routine must be called before PCSetUp() if the user is to be 165 allowed to set the preconditioner method. 166 167 Collective on PC 168 169 Input Parameter: 170 . pc - the preconditioner context 171 172 Level: developer 173 174 .keywords: PC, set, from, options, database 175 176 .seealso: 177 178 @*/ 179 int PCSetFromOptions(PC pc) 180 { 181 int ierr; 182 char type[256]; 183 const char *def; 184 PetscTruth flg; 185 186 PetscFunctionBegin; 187 PetscValidHeaderSpecific(pc,PC_COOKIE); 188 189 if (!PCRegisterAllCalled) {ierr = PCRegisterAll(PETSC_NULL);CHKERRQ(ierr);} 190 ierr = PetscOptionsBegin(pc->comm,pc->prefix,"Preconditioner (PC) Options","PC");CHKERRQ(ierr); 191 if (!pc->type_name) { 192 PetscTruth ismatshell; 193 int size; 194 195 /* 196 Shell matrix (probably) cannot support Bjacobi and ILU 197 */ 198 ierr = MPI_Comm_size(pc->comm,&size);CHKERRQ(ierr); 199 if (pc->pmat) { 200 ierr = PetscTypeCompare((PetscObject)pc->pmat,MATSHELL,&ismatshell);CHKERRQ(ierr); 201 } else { 202 ismatshell = PETSC_FALSE; /* matrix is not yet set, so guess that it will not be MATSHELL */ 203 } 204 /* 205 MATMFFD cannot support BJacobia and ILU 206 */ 207 if (!ismatshell) { 208 ierr = PetscTypeCompare((PetscObject)pc->pmat,MATMFFD,&ismatshell);CHKERRQ(ierr); 209 } 210 211 if (ismatshell) { 212 def = PCNONE; 213 PetscLogInfo(pc,"PCSetOperators:Setting default PC to PCNONE since MATSHELL doesn't support\n\ 214 preconditioners (unless defined by the user)\n"); 215 } else if (size == 1) { 216 ierr = PetscTypeCompare((PetscObject)pc->pmat,MATSEQSBAIJ,&flg);CHKERRQ(ierr); 217 if (flg) { 218 def = PCICC; 219 } else { 220 def = PCILU; 221 } 222 } else { 223 def = PCBJACOBI; 224 } 225 } else { 226 def = pc->type_name; 227 } 228 229 ierr = PetscOptionsList("-pc_type","Preconditioner","PCSetType",PCList,def,type,256,&flg);CHKERRQ(ierr); 230 if (flg) { 231 ierr = PCSetType(pc,type);CHKERRQ(ierr); 232 } 233 234 ierr = PetscOptionsName("-pc_constant_null_space","Add constant null space to preconditioner","PCNullSpaceAttach",&flg);CHKERRQ(ierr); 235 if (flg) { 236 MatNullSpace nsp; 237 238 ierr = MatNullSpaceCreate(pc->comm,1,0,0,&nsp);CHKERRQ(ierr); 239 ierr = PCNullSpaceAttach(pc,nsp);CHKERRQ(ierr); 240 ierr = MatNullSpaceDestroy(nsp);CHKERRQ(ierr); 241 } 242 243 244 /* option is actually checked in PCSetUp() */ 245 if (pc->nullsp) { 246 ierr = PetscOptionsName("-pc_test_null_space","Is provided null space correct","None",&flg);CHKERRQ(ierr); 247 } 248 249 /* 250 Set the type if it was never set. 251 */ 252 if (!pc->type_name) { 253 ierr = PCSetType(pc,def);CHKERRQ(ierr); 254 } 255 256 257 258 if (pc->ops->setfromoptions) { 259 ierr = (*pc->ops->setfromoptions)(pc);CHKERRQ(ierr); 260 } 261 ierr = PetscOptionsEnd();CHKERRQ(ierr); 262 #if defined(__cplusplus) && !defined(PETSC_USE_COMPLEX) && !defined(PETSC_USE_SINGLE) && defined(PETSC_HAVE_CXX_NAMESPACE) 263 ierr = PCESISetFromOptions(pc);CHKERRQ(ierr); 264 #endif 265 PetscFunctionReturn(0); 266 } 267