1 2 /* -------------------------------------------------------------------- 3 4 This file implements a Deflation preconditioner in PETSc as part of PC. 5 You can use this as a starting point for implementing your own 6 preconditioner that is not provided with PETSc. (You might also consider 7 just using PCSHELL) 8 9 The following basic routines are required for each preconditioner. 10 PCCreate_XXX() - Creates a preconditioner context 11 PCSetFromOptions_XXX() - Sets runtime options 12 PCApply_XXX() - Applies the preconditioner 13 PCDestroy_XXX() - Destroys the preconditioner context 14 where the suffix "_XXX" denotes a particular implementation, in 15 this case we use _Deflation (e.g., PCCreate_Deflation, PCApply_Deflation). 16 These routines are actually called via the common user interface 17 routines PCCreate(), PCSetFromOptions(), PCApply(), and PCDestroy(), 18 so the application code interface remains identical for all 19 preconditioners. 20 21 Another key routine is: 22 PCSetUp_XXX() - Prepares for the use of a preconditioner 23 by setting data structures and options. The interface routine PCSetUp() 24 is not usually called directly by the user, but instead is called by 25 PCApply() if necessary. 26 27 Additional basic routines are: 28 PCView_XXX() - Prints details of runtime options that 29 have actually been used. 30 These are called by application codes via the interface routines 31 PCView(). 32 33 The various types of solvers (preconditioners, Krylov subspace methods, 34 nonlinear solvers, timesteppers) are all organized similarly, so the 35 above description applies to these categories also. One exception is 36 that the analogues of PCApply() for these components are KSPSolve(), 37 SNESSolve(), and TSSolve(). 38 39 Additional optional functionality unique to preconditioners is left and 40 right symmetric preconditioner application via PCApplySymmetricLeft() 41 and PCApplySymmetricRight(). The Deflation implementation is 42 PCApplySymmetricLeftOrRight_Deflation(). 43 44 -------------------------------------------------------------------- */ 45 46 /* 47 Include files needed for the Deflation preconditioner: 48 pcimpl.h - private include file intended for use by all preconditioners 49 */ 50 51 #include <../src/ksp/pc/impls/deflation/deflation.h> /*I "petscpc.h" I*/ /* includes for fortran wrappers */ 52 53 const char *const PCDeflationSpaceTypes[] = { 54 "haar", 55 "jacket-haar", 56 "db2", 57 "db4", 58 "db8", 59 "db16", 60 "biorth22", 61 "meyer", 62 "aggregation", 63 "slepc", 64 "slepc-cheap", 65 "user", 66 "DdefSpaceType", 67 "Ddef_SPACE_", 68 0 69 }; 70 71 72 static PetscErrorCode PCDeflationSetSpace_Deflation(PC pc,Mat W,PetscBool transpose) 73 { 74 PC_Deflation *def = (PC_Deflation*)pc->data; 75 PetscErrorCode ierr; 76 77 PetscFunctionBegin; 78 if (transpose) { 79 def->Wt = W; 80 def->W = NULL; 81 } else { 82 def->W = W; 83 } 84 ierr = PetscObjectReference((PetscObject)W);CHKERRQ(ierr); 85 PetscFunctionReturn(0); 86 } 87 88 /* TODO create PCDeflationSetSpaceTranspose? */ 89 /*@ 90 PCDeflationSetSpace - Set deflation space matrix (or its transpose). 91 92 Logically Collective on PC 93 94 Input Parameters: 95 + pc - the preconditioner context 96 . W - deflation matrix 97 - tranpose - indicates that W is an explicit transpose of the deflation matrix 98 99 Level: intermediate 100 101 .seealso: PCDEFLATION 102 @*/ 103 PetscErrorCode PCDeflationSetSpace(PC pc,Mat W,PetscBool transpose) 104 { 105 PetscErrorCode ierr; 106 107 PetscFunctionBegin; 108 PetscValidHeaderSpecific(pc,PC_CLASSID,1); 109 PetscValidHeaderSpecific(W,MAT_CLASSID,2); 110 PetscValidLogicalCollectiveBool(pc,transpose,3); 111 ierr = PetscTryMethod(pc,"PCDeflationSetSpace_C",(PC,Mat,PetscBool),(pc,W,transpose));CHKERRQ(ierr); 112 PetscFunctionReturn(0); 113 } 114 115 static PetscErrorCode PCDeflationSetLvl_Deflation(PC pc,PetscInt current,PetscInt max) 116 { 117 PC_Deflation *def = (PC_Deflation*)pc->data; 118 119 PetscFunctionBegin; 120 if (current) def->nestedlvl = current; 121 def->maxnestedlvl = max; 122 PetscFunctionReturn(0); 123 } 124 125 /*@ 126 PCDeflationSetMaxLvl - Set maximum level of deflation. 127 128 Logically Collective on PC 129 130 Input Parameters: 131 + pc - the preconditioner context 132 - max - maximum deflation level 133 134 Level: intermediate 135 136 .seealso: PCDEFLATION 137 @*/ 138 PetscErrorCode PCDeflationSetMaxLvl(PC pc,PetscInt max) 139 { 140 PetscErrorCode ierr; 141 142 PetscFunctionBegin; 143 PetscValidHeaderSpecific(pc,PC_CLASSID,1); 144 PetscValidLogicalCollectiveInt(pc,max,2); 145 ierr = PetscTryMethod(pc,"PCDeflationSetLvl_C",(PC,PetscInt,PetscInt),(pc,0,max));CHKERRQ(ierr); 146 PetscFunctionReturn(0); 147 } 148 149 static PetscErrorCode PCDeflationSetPC_Deflation(PC pc,PC apc) 150 { 151 PC_Deflation *def = (PC_Deflation*)pc->data; 152 PetscErrorCode ierr; 153 154 PetscFunctionBegin; 155 ierr = PCDestroy(&def->pc);CHKERRQ(ierr); 156 def->pc = apc; 157 ierr = PetscObjectReference((PetscObject)apc);CHKERRQ(ierr); 158 ierr = PetscLogObjectParent((PetscObject)pc,(PetscObject)def->pc);CHKERRQ(ierr); 159 PetscFunctionReturn(0); 160 } 161 162 /*@ 163 PCDeflationSetPC - Set additional preconditioner. 164 165 Logically Collective on PC 166 167 Input Parameters: 168 + pc - the preconditioner context 169 - apc - additional preconditioner 170 171 Level: advanced 172 173 .seealso: PCDEFLATION 174 @*/ 175 PetscErrorCode PCDeflationSetPC(PC pc,PC apc) 176 { 177 PetscErrorCode ierr; 178 179 PetscFunctionBegin; 180 PetscValidHeaderSpecific(pc,PC_CLASSID,1); 181 PetscValidHeaderSpecific(apc,PC_CLASSID,2); 182 PetscCheckSameComm(pc,1,apc,2); 183 ierr = PetscTryMethod(pc,"PCDeflationSetPC_C",(PC,PC),(pc,apc));CHKERRQ(ierr); 184 PetscFunctionReturn(0); 185 } 186 187 static PetscErrorCode PCDeflationGetCoarseKSP_Deflation(PC pc,KSP *ksp) 188 { 189 PC_Deflation *def = (PC_Deflation*)pc->data; 190 191 PetscFunctionBegin; 192 *ksp = def->WtAWinv; 193 PetscFunctionReturn(0); 194 } 195 196 /*@ 197 PCDeflationGetCoarseKSP - Returns a pointer to the coarse problem KSP. 198 199 Not Collective 200 201 Input Parameters: 202 . pc - preconditioner context 203 204 Output Parameter: 205 . ksp - coarse problem KSP context 206 207 Level: developer 208 209 .seealso: PCDEFLATION 210 @*/ 211 PetscErrorCode PCDeflationGetCoarseKSP(PC pc,KSP *ksp) 212 { 213 PetscErrorCode ierr; 214 215 PetscFunctionBegin; 216 PetscValidHeaderSpecific(pc,PC_CLASSID,1); 217 PetscValidPointer(ksp,2); 218 ierr = PetscTryMethod(pc,"PCDeflationGetCoarseKSP_C",(PC,KSP*),(pc,ksp));CHKERRQ(ierr); 219 PetscFunctionReturn(0); 220 } 221 222 /* 223 x <- x + W*(W'*A*W)^{-1}*W'*r = x + Q*r 224 */ 225 static PetscErrorCode PCPreSolve_Deflation(PC pc,KSP ksp,Vec b, Vec x) 226 { 227 PC_Deflation *def = (PC_Deflation*)pc->data; 228 Mat A; 229 Vec r,w1,w2; 230 PetscBool nonzero; 231 PetscErrorCode ierr; 232 233 PetscFunctionBegin; 234 w1 = def->workcoarse[0]; 235 w2 = def->workcoarse[1]; 236 r = def->work; 237 ierr = PCGetOperators(pc,NULL,&A);CHKERRQ(ierr); 238 239 ierr = KSPGetInitialGuessNonzero(ksp,&nonzero);CHKERRQ(ierr); 240 ierr = KSPSetInitialGuessNonzero(ksp,PETSC_TRUE);CHKERRQ(ierr); 241 if (nonzero) { 242 ierr = MatMult(A,x,r);CHKERRQ(ierr); /* r <- b - Ax */ 243 ierr = VecAYPX(r,-1.0,b);CHKERRQ(ierr); 244 } else { 245 ierr = VecCopy(b,r);CHKERRQ(ierr); /* r <- b (x is 0) */ 246 } 247 248 ierr = MatMultTranspose(def->W,r,w1);CHKERRQ(ierr); /* w1 <- W'*r */ 249 ierr = KSPSolve(def->WtAWinv,w1,w2);CHKERRQ(ierr); /* w2 <- (W'*A*W)^{-1}*w1 */ 250 ierr = MatMult(def->W,w2,r);CHKERRQ(ierr); /* r <- W*w2 */ 251 ierr = VecAYPX(x,1.0,r);CHKERRQ(ierr); 252 PetscFunctionReturn(0); 253 } 254 255 /* 256 if (def->correct) { 257 z <- r - W*(W'*A*W)^{-1}*W'*(A*r -r) = (P-Q)*M^{-1}*r 258 } else { 259 z <- r - W*(W'*A*W)^{-1}*W'*A*r = P*M^{-1}*r 260 } 261 */ 262 static PetscErrorCode PCApply_Deflation(PC pc,Vec r,Vec z) 263 { 264 PC_Deflation *def = (PC_Deflation*)pc->data; 265 Mat A; 266 Vec u,w1,w2; 267 PetscErrorCode ierr; 268 269 PetscFunctionBegin; 270 w1 = def->workcoarse[0]; 271 w2 = def->workcoarse[1]; 272 u = def->work; 273 ierr = PCGetOperators(pc,NULL,&A);CHKERRQ(ierr); 274 275 ierr = PCApply(def->pc,r,z);CHKERRQ(ierr); 276 if (!def->init) { 277 if (!def->AW) { 278 ierr = MatMult(A,z,u);CHKERRQ(ierr); /* u <- A*z */ 279 if (def->correct) ierr = VecAXPY(u,-1.0*def->correctfact,z);CHKERRQ(ierr); /* u <- A*z -z */ 280 ierr = MatMultTranspose(def->W,u,w1);CHKERRQ(ierr); /* w1 <- W'*u */ 281 } else { 282 /* ONLY if A SYM */ 283 ierr = MatMultTranspose(def->AW,z,w1);CHKERRQ(ierr); /* w1 <- W'*A*r */ 284 if (def->correct) { 285 ierr = MatMultTranspose(def->W,z,w2);CHKERRQ(ierr); /* w2 <- W'*u */ 286 ierr = VecAXPY(w1,-1.0*def->correctfact,w2);CHKERRQ(ierr); /* w1 <- w1 - w2 */ 287 } 288 } 289 ierr = KSPSolve(def->WtAWinv,w1,w2);CHKERRQ(ierr); /* w2 <- (W'*A*W)^{-1}*w1 */ 290 ierr = MatMult(def->W,w2,u);CHKERRQ(ierr); /* u <- W*w2 */ 291 ierr = VecAXPY(z,-1.0,u);CHKERRQ(ierr); /* z <- z - u */ 292 } 293 PetscFunctionReturn(0); 294 } 295 296 static PetscErrorCode PCSetUp_Deflation(PC pc) 297 { 298 PC_Deflation *def = (PC_Deflation*)pc->data; 299 KSP innerksp; 300 PC pcinner; 301 Mat Amat,nextDef=NULL,*mats; 302 PetscInt i,m,red,size,commsize; 303 PetscBool match,flgspd,transp=PETSC_FALSE; 304 MatCompositeType ctype; 305 MPI_Comm comm; 306 const char *prefix; 307 PetscErrorCode ierr; 308 309 PetscFunctionBegin; 310 if (pc->setupcalled) PetscFunctionReturn(0); 311 ierr = PetscObjectGetComm((PetscObject)pc,&comm);CHKERRQ(ierr); 312 ierr = PCGetOperators(pc,NULL,&Amat);CHKERRQ(ierr); 313 314 /* compute a deflation space */ 315 if (def->W || def->Wt) { 316 def->spacetype = PC_DEFLATION_SPACE_USER; 317 } else { 318 ierr = PCDeflationComputeSpace(pc);CHKERRQ(ierr); 319 } 320 321 /* nested deflation */ 322 if (def->W) { 323 ierr = PetscObjectTypeCompare((PetscObject)def->W,MATCOMPOSITE,&match);CHKERRQ(ierr); 324 if (match) { 325 ierr = MatCompositeGetType(def->W,&ctype);CHKERRQ(ierr); 326 ierr = MatCompositeGetNumberMat(def->W,&size);CHKERRQ(ierr); 327 } 328 } else { 329 ierr = MatCreateTranspose(def->Wt,&def->W);CHKERRQ(ierr); 330 ierr = PetscObjectTypeCompare((PetscObject)def->Wt,MATCOMPOSITE,&match);CHKERRQ(ierr); 331 if (match) { 332 ierr = MatCompositeGetType(def->Wt,&ctype);CHKERRQ(ierr); 333 ierr = MatCompositeGetNumberMat(def->Wt,&size);CHKERRQ(ierr); 334 } 335 transp = PETSC_TRUE; 336 } 337 if (match && ctype == MAT_COMPOSITE_MULTIPLICATIVE) { 338 if (!transp) { 339 if (def->nestedlvl < def->maxnestedlvl) { 340 ierr = PetscMalloc1(size,&mats);CHKERRQ(ierr); 341 for (i=0; i<size; i++) { 342 ierr = MatCompositeGetMat(def->W,i,&mats[i]);CHKERRQ(ierr); 343 } 344 size -= 1; 345 ierr = MatDestroy(&def->W);CHKERRQ(ierr); 346 def->W = mats[size]; 347 ierr = PetscObjectReference((PetscObject)mats[size]);CHKERRQ(ierr); 348 if (size > 1) { 349 ierr = MatCreateComposite(comm,size,mats,&nextDef);CHKERRQ(ierr); 350 ierr = MatCompositeSetType(nextDef,MAT_COMPOSITE_MULTIPLICATIVE);CHKERRQ(ierr); 351 } else { 352 nextDef = mats[0]; 353 ierr = PetscObjectReference((PetscObject)mats[0]);CHKERRQ(ierr); 354 } 355 ierr = PetscFree(mats);CHKERRQ(ierr); 356 } else { 357 /* ierr = MatCompositeSetMergeType(def->W,MAT_COMPOSITE_MERGE_LEFT);CHKERRQ(ierr); */ 358 ierr = MatCompositeMerge(def->W);CHKERRQ(ierr); 359 } 360 } else { 361 if (def->nestedlvl < def->maxnestedlvl) { 362 ierr = PetscMalloc1(size,&mats);CHKERRQ(ierr); 363 for (i=0; i<size; i++) { 364 ierr = MatCompositeGetMat(def->Wt,i,&mats[i]);CHKERRQ(ierr); 365 } 366 size -= 1; 367 ierr = MatDestroy(&def->Wt);CHKERRQ(ierr); 368 def->Wt = mats[0]; 369 ierr = PetscObjectReference((PetscObject)mats[0]);CHKERRQ(ierr); 370 if (size > 1) { 371 ierr = MatCreateComposite(comm,size,&mats[1],&nextDef);CHKERRQ(ierr); 372 ierr = MatCompositeSetType(nextDef,MAT_COMPOSITE_MULTIPLICATIVE);CHKERRQ(ierr); 373 } else { 374 nextDef = mats[1]; 375 ierr = PetscObjectReference((PetscObject)mats[1]);CHKERRQ(ierr); 376 } 377 ierr = PetscFree(mats);CHKERRQ(ierr); 378 } else { 379 /* ierr = MatCompositeSetMergeType(def->W,MAT_COMPOSITE_MERGE_LEFT);CHKERRQ(ierr); */ 380 ierr = MatCompositeMerge(def->Wt);CHKERRQ(ierr); 381 } 382 } 383 } 384 385 if (transp) { 386 ierr = MatDestroy(&def->W);CHKERRQ(ierr); 387 ierr = MatTranspose(def->Wt,MAT_INITIAL_MATRIX,&def->W);CHKERRQ(ierr); 388 } 389 390 391 ierr = PCGetOptionsPrefix(pc,&prefix);CHKERRQ(ierr); 392 393 /* setup coarse problem */ 394 if (!def->WtAWinv) { 395 ierr = MatGetSize(def->W,NULL,&m);CHKERRQ(ierr); 396 if (!def->WtAW) { 397 /* TODO add implicit product version ? */ 398 if (!def->AW) { 399 ierr = MatPtAP(Amat,def->W,MAT_INITIAL_MATRIX,PETSC_DEFAULT,&def->WtAW);CHKERRQ(ierr); 400 } else { 401 ierr = MatTransposeMatMult(def->W,def->AW,MAT_INITIAL_MATRIX,PETSC_DEFAULT,&def->WtAW);CHKERRQ(ierr); 402 } 403 /* TODO create MatInheritOption(Mat,MatOption) */ 404 ierr = MatGetOption(Amat,MAT_SPD,&flgspd);CHKERRQ(ierr); 405 ierr = MatSetOption(def->WtAW,MAT_SPD,flgspd);CHKERRQ(ierr); 406 #if defined(PETSC_USE_DEBUG) 407 /* Check WtAW is not sigular */ 408 PetscReal *norms; 409 ierr = PetscMalloc1(m,&norms);CHKERRQ(ierr); 410 ierr = MatGetColumnNorms(def->WtAW,NORM_INFINITY,norms);CHKERRQ(ierr); 411 for (i=0; i<m; i++) { 412 if (norms[i] < 100*PETSC_MACHINE_EPSILON) { 413 SETERRQ1(comm,PETSC_ERR_SUP,"Column %D of W is in kernel of A.",i); 414 } 415 } 416 ierr = PetscFree(norms);CHKERRQ(ierr); 417 #endif 418 } else { 419 ierr = MatGetOption(def->WtAW,MAT_SPD,&flgspd);CHKERRQ(ierr); 420 } 421 /* TODO use MATINV */ 422 ierr = KSPCreate(comm,&def->WtAWinv);CHKERRQ(ierr); 423 ierr = KSPSetOperators(def->WtAWinv,def->WtAW,def->WtAW);CHKERRQ(ierr); 424 ierr = KSPGetPC(def->WtAWinv,&pcinner);CHKERRQ(ierr); 425 /* Setup KSP and PC */ 426 if (nextDef) { /* next level for multilevel deflation */ 427 innerksp = def->WtAWinv; 428 /* set default KSPtype */ 429 if (!def->ksptype) { 430 def->ksptype = KSPFGMRES; 431 if (flgspd) { /* SPD system */ 432 def->ksptype = KSPFCG; 433 } 434 } 435 ierr = KSPSetType(innerksp,def->ksptype);CHKERRQ(ierr); /* TODO iherit from KSP */ 436 ierr = PCSetType(pcinner,PCDEFLATION);CHKERRQ(ierr); /* TODO create coarse preconditinoner M_c = WtMW ? */ 437 ierr = PCDeflationSetSpace(pcinner,nextDef,transp);CHKERRQ(ierr); 438 ierr = PCDeflationSetLvl_Deflation(pcinner,def->nestedlvl+1,def->maxnestedlvl);CHKERRQ(ierr); 439 /* inherit options TODO if not set */ 440 ((PC_Deflation*)(pcinner->data))->ksptype = def->ksptype; 441 ((PC_Deflation*)(pcinner->data))->correct = def->correct; 442 ierr = MatDestroy(&nextDef);CHKERRQ(ierr); 443 } else { /* the last level */ 444 ierr = KSPSetType(def->WtAWinv,KSPPREONLY);CHKERRQ(ierr); 445 ierr = PCSetType(pcinner,PCTELESCOPE);CHKERRQ(ierr); 446 /* ugly hack to not have overwritten PCTELESCOPE */ 447 if (prefix) { 448 ierr = KSPSetOptionsPrefix(def->WtAWinv,prefix);CHKERRQ(ierr); 449 } 450 ierr = KSPAppendOptionsPrefix(def->WtAWinv,"tel_");CHKERRQ(ierr); 451 ierr = PCSetFromOptions(pcinner);CHKERRQ(ierr); 452 /* Reduction factor choice */ 453 red = def->reductionfact; 454 if (red < 0) { 455 ierr = MPI_Comm_size(comm,&commsize);CHKERRQ(ierr); 456 red = ceil((float)commsize/ceil((float)m/commsize)); 457 ierr = PetscObjectTypeCompareAny((PetscObject)(def->WtAW),&match,MATSEQDENSE,MATMPIDENSE,MATDENSE,"");CHKERRQ(ierr); 458 if (match) red = commsize; 459 ierr = PetscInfo1(pc,"Auto choosing reduction factor %D\n",red);CHKERRQ(ierr); /* TODO add level? */ 460 } 461 ierr = PCTelescopeSetReductionFactor(pcinner,red);CHKERRQ(ierr); 462 ierr = PCSetUp(pcinner);CHKERRQ(ierr); 463 ierr = PCTelescopeGetKSP(pcinner,&innerksp);CHKERRQ(ierr); 464 if (innerksp) { 465 ierr = KSPGetPC(innerksp,&pcinner);CHKERRQ(ierr); 466 /* TODO Cholesky if flgspd? */ 467 ierr = PCSetType(pcinner,PCLU);CHKERRQ(ierr); 468 //TODO remove explicit matSolverPackage 469 if (commsize == red) { 470 ierr = PCFactorSetMatSolverType(pcinner,MATSOLVERSUPERLU);CHKERRQ(ierr); 471 } else { 472 ierr = PCFactorSetMatSolverType(pcinner,MATSOLVERSUPERLU_DIST);CHKERRQ(ierr); 473 } 474 } 475 } 476 477 if (innerksp) { 478 /* TODO use def_[lvl]_ if lvl > 0? */ 479 if (prefix) { 480 ierr = KSPSetOptionsPrefix(innerksp,prefix);CHKERRQ(ierr); 481 } 482 ierr = KSPAppendOptionsPrefix(innerksp,"def_");CHKERRQ(ierr); 483 ierr = KSPSetFromOptions(innerksp);CHKERRQ(ierr); 484 ierr = KSPSetUp(innerksp);CHKERRQ(ierr); 485 } 486 } 487 ierr = KSPSetFromOptions(def->WtAWinv);CHKERRQ(ierr); 488 ierr = KSPSetUp(def->WtAWinv);CHKERRQ(ierr); 489 490 if (!def->pc) { 491 ierr = PCCreate(comm,&def->pc);CHKERRQ(ierr); 492 ierr = PCSetOperators(def->pc,Amat,Amat);CHKERRQ(ierr); 493 ierr = PCSetType(def->pc,PCNONE);CHKERRQ(ierr); 494 if (prefix) { 495 ierr = PCSetOptionsPrefix(def->pc,prefix);CHKERRQ(ierr); 496 } 497 ierr = PCAppendOptionsPrefix(def->pc,"def_pc_");CHKERRQ(ierr); 498 ierr = PCSetFromOptions(def->pc);CHKERRQ(ierr); 499 ierr = PCSetUp(def->pc);CHKERRQ(ierr); 500 } 501 502 /* create work vecs */ 503 ierr = MatCreateVecs(Amat,NULL,&def->work);CHKERRQ(ierr); 504 ierr = KSPCreateVecs(def->WtAWinv,2,&def->workcoarse,0,NULL);CHKERRQ(ierr); 505 PetscFunctionReturn(0); 506 } 507 508 static PetscErrorCode PCReset_Deflation(PC pc) 509 { 510 PC_Deflation *def = (PC_Deflation*)pc->data; 511 PetscErrorCode ierr; 512 513 PetscFunctionBegin; 514 ierr = VecDestroy(&def->work);CHKERRQ(ierr); 515 ierr = VecDestroyVecs(2,&def->workcoarse);CHKERRQ(ierr); 516 ierr = MatDestroy(&def->W);CHKERRQ(ierr); 517 ierr = MatDestroy(&def->Wt);CHKERRQ(ierr); 518 ierr = MatDestroy(&def->AW);CHKERRQ(ierr); 519 ierr = MatDestroy(&def->WtAW);CHKERRQ(ierr); 520 ierr = KSPDestroy(&def->WtAWinv);CHKERRQ(ierr); 521 ierr = PCDestroy(&def->pc);CHKERRQ(ierr); 522 PetscFunctionReturn(0); 523 } 524 525 /* 526 PCDestroy_Deflation - Destroys the private context for the Deflation preconditioner 527 that was created with PCCreate_Deflation(). 528 529 Input Parameter: 530 . pc - the preconditioner context 531 532 Application Interface Routine: PCDestroy() 533 */ 534 static PetscErrorCode PCDestroy_Deflation(PC pc) 535 { 536 PetscErrorCode ierr; 537 538 PetscFunctionBegin; 539 ierr = PCReset_Deflation(pc);CHKERRQ(ierr); 540 ierr = PetscFree(pc->data);CHKERRQ(ierr); 541 PetscFunctionReturn(0); 542 } 543 544 static PetscErrorCode PCView_Deflation(PC pc,PetscViewer viewer) 545 { 546 PC_Deflation *def = (PC_Deflation*)pc->data; 547 PetscBool iascii; 548 PetscErrorCode ierr; 549 550 PetscFunctionBegin; 551 ierr = PetscObjectTypeCompare((PetscObject)viewer,PETSCVIEWERASCII,&iascii);CHKERRQ(ierr); 552 if (iascii) { 553 //if (cg->adaptiveconv) { 554 // ierr = PetscViewerASCIIPrintf(viewer," DCG: using adaptive precision for inner solve with C=%.1e\n",cg->adaptiveconst);CHKERRQ(ierr); 555 //} 556 if (def->correct) { 557 ierr = PetscViewerASCIIPrintf(viewer," Using CP correction\n");CHKERRQ(ierr); 558 } 559 if (!def->nestedlvl) { 560 ierr = PetscViewerASCIIPrintf(viewer," Deflation space type: %s\n",PCDeflationSpaceTypes[def->spacetype]);CHKERRQ(ierr); 561 ierr = PetscViewerASCIIPrintf(viewer," DCG %s\n",def->extendsp ? "extended" : "truncated");CHKERRQ(ierr); 562 } 563 564 ierr = PetscViewerASCIIPrintf(viewer,"--- Additional PC\n");CHKERRQ(ierr); 565 ierr = PetscViewerASCIIPushTab(viewer);CHKERRQ(ierr); 566 ierr = PCView(def->pc,viewer);CHKERRQ(ierr); 567 ierr = PetscViewerASCIIPopTab(viewer);CHKERRQ(ierr); 568 569 ierr = PetscViewerASCIIPrintf(viewer,"--- Coarse solver\n");CHKERRQ(ierr); 570 ierr = PetscViewerASCIIPushTab(viewer);CHKERRQ(ierr); 571 ierr = KSPView(def->WtAWinv,viewer);CHKERRQ(ierr); 572 ierr = PetscViewerASCIIPopTab(viewer);CHKERRQ(ierr); 573 } 574 PetscFunctionReturn(0); 575 } 576 577 static PetscErrorCode PCSetFromOptions_Deflation(PetscOptionItems *PetscOptionsObject,PC pc) 578 { 579 PC_Deflation *def = (PC_Deflation*)pc->data; 580 PetscErrorCode ierr; 581 582 PetscFunctionBegin; 583 ierr = PetscOptionsHead(PetscOptionsObject,"Deflation options");CHKERRQ(ierr); 584 ierr = PetscOptionsEnum("-pc_deflation_compute_space","Compute deflation space","PCDeflationSetSpace",PCDeflationSpaceTypes,(PetscEnum)def->spacetype,(PetscEnum*)&def->spacetype,NULL);CHKERRQ(ierr); 585 ierr = PetscOptionsInt("-pc_deflation_compute_space_size","Set size of the deflation space to compute","PCDeflationSetSpace",def->spacesize,&def->spacesize,NULL);CHKERRQ(ierr); 586 ierr = PetscOptionsBool("-pc_deflation_space_extend","Extend deflation space instead of truncating (wavelets)","PCDeflation",def->extendsp,&def->extendsp,NULL);CHKERRQ(ierr); 587 //TODO add set function and fix manpages 588 ierr = PetscOptionsBool("-pc_deflation_initdef","Use only initialization step - Initdef","PCDeflation",def->init,&def->init,NULL);CHKERRQ(ierr); 589 ierr = PetscOptionsBool("-pc_deflation_correct","Add coarse problem correction Q to P","PCDeflation",def->correct,&def->correct,NULL);CHKERRQ(ierr); 590 ierr = PetscOptionsReal("-pc_deflation_correct_val","Set multiple of Q to use as coarse problem correction","PCDeflation",def->correctfact,&def->correctfact,NULL);CHKERRQ(ierr); 591 ierr = PetscOptionsInt("-pc_deflation_redfact","Reduction factor for coarse problem solution","PCDeflation",def->reductionfact,&def->reductionfact,NULL);CHKERRQ(ierr); 592 ierr = PetscOptionsInt("-pc_deflation_max_nested_lvl","Maximum of nested deflation levels","PCDeflation",def->maxnestedlvl,&def->maxnestedlvl,NULL);CHKERRQ(ierr); 593 ierr = PetscOptionsTail();CHKERRQ(ierr); 594 PetscFunctionReturn(0); 595 } 596 597 /*MC 598 PCDEFLATION - Deflation preconditioner shifts part of the spectrum to zero (deflates) 599 or to a predefined value 600 601 Options Database Key: 602 + -pc_deflation_type <init,pre,post> - selects approach to deflation (default: pre) 603 - -pc_jacobi_abs - use the absolute value of the diagonal entry 604 605 Level: beginner 606 607 Notes: 608 todo 609 610 .seealso: PCCreate(), PCSetType(), PCType (for list of available types), PC, 611 PCDeflationSetType(), PCDeflationSetSpace() 612 M*/ 613 614 PETSC_EXTERN PetscErrorCode PCCreate_Deflation(PC pc) 615 { 616 PC_Deflation *def; 617 PetscErrorCode ierr; 618 619 PetscFunctionBegin; 620 ierr = PetscNewLog(pc,&def);CHKERRQ(ierr); 621 pc->data = (void*)def; 622 623 def->init = PETSC_FALSE; 624 def->correct = PETSC_FALSE; 625 def->correctfact = 1.0; 626 def->reductionfact = -1; 627 def->spacetype = PC_DEFLATION_SPACE_HAAR; 628 def->spacesize = 1; 629 def->extendsp = PETSC_FALSE; 630 def->nestedlvl = 0; 631 def->maxnestedlvl = 0; 632 633 /* 634 Set the pointers for the functions that are provided above. 635 Now when the user-level routines (such as PCApply(), PCDestroy(), etc.) 636 are called, they will automatically call these functions. Note we 637 choose not to provide a couple of these functions since they are 638 not needed. 639 */ 640 pc->ops->apply = PCApply_Deflation; 641 pc->ops->applytranspose = PCApply_Deflation; 642 pc->ops->presolve = PCPreSolve_Deflation; 643 pc->ops->postsolve = 0; 644 pc->ops->setup = PCSetUp_Deflation; 645 pc->ops->reset = PCReset_Deflation; 646 pc->ops->destroy = PCDestroy_Deflation; 647 pc->ops->setfromoptions = PCSetFromOptions_Deflation; 648 pc->ops->view = PCView_Deflation; 649 pc->ops->applyrichardson = 0; 650 pc->ops->applysymmetricleft = 0; 651 pc->ops->applysymmetricright = 0; 652 653 ierr = PetscObjectComposeFunction((PetscObject)pc,"PCDeflationSetSpace_C",PCDeflationSetSpace_Deflation);CHKERRQ(ierr); 654 ierr = PetscObjectComposeFunction((PetscObject)pc,"PCDeflationSetLvl_C",PCDeflationSetLvl_Deflation);CHKERRQ(ierr); 655 ierr = PetscObjectComposeFunction((PetscObject)pc,"PCDeflationSetPC_C",PCDeflationSetPC_Deflation);CHKERRQ(ierr); 656 ierr = PetscObjectComposeFunction((PetscObject)pc,"PCDeflationGetCoarseKSP_C",PCDeflationGetCoarseKSP_Deflation);CHKERRQ(ierr); 657 PetscFunctionReturn(0); 658 } 659 660