1 #include <../src/ksp/pc/impls/deflation/deflation.h> /*I "petscksp.h" I*/ /* includes for fortran wrappers */ 2 3 const char *const PCDeflationSpaceTypes[] = { 4 "haar", 5 "db2", 6 "db4", 7 "db8", 8 "db16", 9 "biorth22", 10 "meyer", 11 "aggregation", 12 "user", 13 "PCDeflationSpaceType", 14 "PC_DEFLATION_SPACE_", 15 NULL 16 }; 17 18 static PetscErrorCode PCDeflationSetInitOnly_Deflation(PC pc,PetscBool flg) 19 { 20 PC_Deflation *def = (PC_Deflation*)pc->data; 21 22 PetscFunctionBegin; 23 def->init = flg; 24 PetscFunctionReturn(0); 25 } 26 27 /*@ 28 PCDeflationSetInitOnly - Do only initialization step. 29 Sets initial guess to the solution on the deflation space but does not apply 30 the deflation preconditioner. The additional preconditioner is still applied. 31 32 Logically Collective 33 34 Input Parameters: 35 + pc - the preconditioner context 36 - flg - default PETSC_FALSE 37 38 Options Database Keys: 39 . -pc_deflation_init_only <false> - if true computes only the special guess 40 41 Level: intermediate 42 43 .seealso: PCDEFLATION 44 @*/ 45 PetscErrorCode PCDeflationSetInitOnly(PC pc,PetscBool flg) 46 { 47 PetscFunctionBegin; 48 PetscValidHeaderSpecific(pc,PC_CLASSID,1); 49 PetscValidLogicalCollectiveBool(pc,flg,2); 50 CHKERRQ(PetscTryMethod(pc,"PCDeflationSetInitOnly_C",(PC,PetscBool),(pc,flg))); 51 PetscFunctionReturn(0); 52 } 53 54 static PetscErrorCode PCDeflationSetLevels_Deflation(PC pc,PetscInt current,PetscInt max) 55 { 56 PC_Deflation *def = (PC_Deflation*)pc->data; 57 58 PetscFunctionBegin; 59 if (current) def->lvl = current; 60 def->maxlvl = max; 61 PetscFunctionReturn(0); 62 } 63 64 /*@ 65 PCDeflationSetLevels - Set the maximum level of deflation nesting. 66 67 Logically Collective 68 69 Input Parameters: 70 + pc - the preconditioner context 71 - max - maximum deflation level 72 73 Options Database Keys: 74 . -pc_deflation_max_lvl <0> - maximum number of levels for multilevel deflation 75 76 Level: intermediate 77 78 .seealso: PCDeflationSetSpaceToCompute(), PCDeflationSetSpace(), PCDEFLATION 79 @*/ 80 PetscErrorCode PCDeflationSetLevels(PC pc,PetscInt max) 81 { 82 PetscFunctionBegin; 83 PetscValidHeaderSpecific(pc,PC_CLASSID,1); 84 PetscValidLogicalCollectiveInt(pc,max,2); 85 CHKERRQ(PetscTryMethod(pc,"PCDeflationSetLevels_C",(PC,PetscInt,PetscInt),(pc,0,max))); 86 PetscFunctionReturn(0); 87 } 88 89 static PetscErrorCode PCDeflationSetReductionFactor_Deflation(PC pc,PetscInt red) 90 { 91 PC_Deflation *def = (PC_Deflation*)pc->data; 92 93 PetscFunctionBegin; 94 def->reductionfact = red; 95 PetscFunctionReturn(0); 96 } 97 98 /*@ 99 PCDeflationSetReductionFactor - Set reduction factor for the bottom PCTELESCOPE coarse problem solver. 100 101 Logically Collective 102 103 Input Parameters: 104 + pc - the preconditioner context 105 - red - reduction factor (or PETSC_DETERMINE) 106 107 Options Database Keys: 108 . -pc_deflation_reduction_factor <\-1> - reduction factor on bottom level coarse problem for PCTELESCOPE 109 110 Notes: 111 Default is computed based on the size of the coarse problem. 112 113 Level: intermediate 114 115 .seealso: PCTELESCOPE, PCDEFLATION 116 @*/ 117 PetscErrorCode PCDeflationSetReductionFactor(PC pc,PetscInt red) 118 { 119 PetscFunctionBegin; 120 PetscValidHeaderSpecific(pc,PC_CLASSID,1); 121 PetscValidLogicalCollectiveInt(pc,red,2); 122 CHKERRQ(PetscTryMethod(pc,"PCDeflationSetReductionFactor_C",(PC,PetscInt),(pc,red))); 123 PetscFunctionReturn(0); 124 } 125 126 static PetscErrorCode PCDeflationSetCorrectionFactor_Deflation(PC pc,PetscScalar fact) 127 { 128 PC_Deflation *def = (PC_Deflation*)pc->data; 129 130 PetscFunctionBegin; 131 /* TODO PETSC_DETERMINE -> compute max eigenvalue with power method */ 132 def->correct = PETSC_TRUE; 133 def->correctfact = fact; 134 if (def->correct == 0.0) { 135 def->correct = PETSC_FALSE; 136 } 137 PetscFunctionReturn(0); 138 } 139 140 /*@ 141 PCDeflationSetCorrectionFactor - Set coarse problem correction factor. 142 The Preconditioner becomes P*M^{-1} + fact*Q. 143 144 Logically Collective 145 146 Input Parameters: 147 + pc - the preconditioner context 148 - fact - correction factor 149 150 Options Database Keys: 151 + -pc_deflation_correction <false> - if true apply coarse problem correction 152 - -pc_deflation_correction_factor <1.0> - sets coarse problem correction factor 153 154 Notes: 155 Any non-zero fact enables the coarse problem correction. 156 157 Level: intermediate 158 159 .seealso: PCDEFLATION 160 @*/ 161 PetscErrorCode PCDeflationSetCorrectionFactor(PC pc,PetscScalar fact) 162 { 163 PetscFunctionBegin; 164 PetscValidHeaderSpecific(pc,PC_CLASSID,1); 165 PetscValidLogicalCollectiveScalar(pc,fact,2); 166 CHKERRQ(PetscTryMethod(pc,"PCDeflationSetCorrectionFactor_C",(PC,PetscScalar),(pc,fact))); 167 PetscFunctionReturn(0); 168 } 169 170 static PetscErrorCode PCDeflationSetSpaceToCompute_Deflation(PC pc,PCDeflationSpaceType type,PetscInt size) 171 { 172 PC_Deflation *def = (PC_Deflation*)pc->data; 173 174 PetscFunctionBegin; 175 if (type) def->spacetype = type; 176 if (size > 0) def->spacesize = size; 177 PetscFunctionReturn(0); 178 } 179 180 /*@ 181 PCDeflationSetSpaceToCompute - Set deflation space type and size to compute. 182 183 Logically Collective 184 185 Input Parameters: 186 + pc - the preconditioner context 187 . type - deflation space type to compute (or PETSC_IGNORE) 188 - size - size of the space to compute (or PETSC_DEFAULT) 189 190 Options Database Keys: 191 + -pc_deflation_compute_space <haar> - compute PCDeflationSpaceType deflation space 192 - -pc_deflation_compute_space_size <1> - size of the deflation space 193 194 Notes: 195 For wavelet-based deflation, size represents number of levels. 196 197 The deflation space is computed in PCSetUp(). 198 199 Level: intermediate 200 201 .seealso: PCDeflationSetLevels(), PCDEFLATION 202 @*/ 203 PetscErrorCode PCDeflationSetSpaceToCompute(PC pc,PCDeflationSpaceType type,PetscInt size) 204 { 205 PetscFunctionBegin; 206 PetscValidHeaderSpecific(pc,PC_CLASSID,1); 207 if (type) PetscValidLogicalCollectiveEnum(pc,type,2); 208 if (size > 0) PetscValidLogicalCollectiveInt(pc,size,3); 209 CHKERRQ(PetscTryMethod(pc,"PCDeflationSetSpaceToCompute_C",(PC,PCDeflationSpaceType,PetscInt),(pc,type,size))); 210 PetscFunctionReturn(0); 211 } 212 213 static PetscErrorCode PCDeflationSetSpace_Deflation(PC pc,Mat W,PetscBool transpose) 214 { 215 PC_Deflation *def = (PC_Deflation*)pc->data; 216 217 PetscFunctionBegin; 218 /* possibly allows W' = Wt (which is valid but not tested) */ 219 CHKERRQ(PetscObjectReference((PetscObject)W)); 220 if (transpose) { 221 CHKERRQ(MatDestroy(&def->Wt)); 222 def->Wt = W; 223 } else { 224 CHKERRQ(MatDestroy(&def->W)); 225 def->W = W; 226 } 227 PetscFunctionReturn(0); 228 } 229 230 /*@ 231 PCDeflationSetSpace - Set the deflation space matrix (or its (Hermitian) transpose). 232 233 Logically Collective 234 235 Input Parameters: 236 + pc - the preconditioner context 237 . W - deflation matrix 238 - transpose - indicates that W is an explicit transpose of the deflation matrix 239 240 Notes: 241 Setting W as a multipliplicative MATCOMPOSITE enables use of the multilevel 242 deflation. If W = W0*W1*W2*...*Wn, W0 is taken as the first deflation space and 243 the coarse problem (W0'*A*W0)^{-1} is again preconditioned by deflation with 244 W1 as the deflation matrix. This repeats until the maximum level set by 245 PCDeflationSetLevels() is reached or there are no more matrices available. 246 If there are matrices left after reaching the maximum level, 247 they are merged into a deflation matrix ...*W{n-1}*Wn. 248 249 Level: intermediate 250 251 .seealso: PCDeflationSetLevels(), PCDEFLATION 252 @*/ 253 PetscErrorCode PCDeflationSetSpace(PC pc,Mat W,PetscBool transpose) 254 { 255 PetscFunctionBegin; 256 PetscValidHeaderSpecific(pc,PC_CLASSID,1); 257 PetscValidHeaderSpecific(W,MAT_CLASSID,2); 258 PetscValidLogicalCollectiveBool(pc,transpose,3); 259 CHKERRQ(PetscTryMethod(pc,"PCDeflationSetSpace_C",(PC,Mat,PetscBool),(pc,W,transpose))); 260 PetscFunctionReturn(0); 261 } 262 263 static PetscErrorCode PCDeflationSetProjectionNullSpaceMat_Deflation(PC pc,Mat mat) 264 { 265 PC_Deflation *def = (PC_Deflation*)pc->data; 266 267 PetscFunctionBegin; 268 CHKERRQ(PetscObjectReference((PetscObject)mat)); 269 CHKERRQ(MatDestroy(&def->WtA)); 270 def->WtA = mat; 271 CHKERRQ(PetscLogObjectParent((PetscObject)pc,(PetscObject)def->WtA)); 272 PetscFunctionReturn(0); 273 } 274 275 /*@ 276 PCDeflationSetProjectionNullSpaceMat - Set the projection null space matrix (W'*A). 277 278 Collective 279 280 Input Parameters: 281 + pc - preconditioner context 282 - mat - projection null space matrix 283 284 Level: developer 285 286 .seealso: PCDEFLATION 287 @*/ 288 PetscErrorCode PCDeflationSetProjectionNullSpaceMat(PC pc,Mat mat) 289 { 290 PetscFunctionBegin; 291 PetscValidHeaderSpecific(pc,PC_CLASSID,1); 292 PetscValidHeaderSpecific(mat,MAT_CLASSID,2); 293 CHKERRQ(PetscTryMethod(pc,"PCDeflationSetProjectionNullSpaceMat_C",(PC,Mat),(pc,mat))); 294 PetscFunctionReturn(0); 295 } 296 297 static PetscErrorCode PCDeflationSetCoarseMat_Deflation(PC pc,Mat mat) 298 { 299 PC_Deflation *def = (PC_Deflation*)pc->data; 300 301 PetscFunctionBegin; 302 CHKERRQ(PetscObjectReference((PetscObject)mat)); 303 CHKERRQ(MatDestroy(&def->WtAW)); 304 def->WtAW = mat; 305 CHKERRQ(PetscLogObjectParent((PetscObject)pc,(PetscObject)def->WtAW)); 306 PetscFunctionReturn(0); 307 } 308 309 /*@ 310 PCDeflationSetCoarseMat - Set the coarse problem Mat. 311 312 Collective 313 314 Input Parameters: 315 + pc - preconditioner context 316 - mat - coarse problem mat 317 318 Level: developer 319 320 .seealso: PCDEFLATION 321 @*/ 322 PetscErrorCode PCDeflationSetCoarseMat(PC pc,Mat mat) 323 { 324 PetscFunctionBegin; 325 PetscValidHeaderSpecific(pc,PC_CLASSID,1); 326 PetscValidHeaderSpecific(mat,MAT_CLASSID,2); 327 CHKERRQ(PetscTryMethod(pc,"PCDeflationSetCoarseMat_C",(PC,Mat),(pc,mat))); 328 PetscFunctionReturn(0); 329 } 330 331 static PetscErrorCode PCDeflationGetCoarseKSP_Deflation(PC pc,KSP *ksp) 332 { 333 PC_Deflation *def = (PC_Deflation*)pc->data; 334 335 PetscFunctionBegin; 336 *ksp = def->WtAWinv; 337 PetscFunctionReturn(0); 338 } 339 340 /*@ 341 PCDeflationGetCoarseKSP - Returns the coarse problem KSP. 342 343 Not Collective 344 345 Input Parameters: 346 . pc - preconditioner context 347 348 Output Parameters: 349 . ksp - coarse problem KSP context 350 351 Level: advanced 352 353 .seealso: PCDEFLATION 354 @*/ 355 PetscErrorCode PCDeflationGetCoarseKSP(PC pc,KSP *ksp) 356 { 357 PetscFunctionBegin; 358 PetscValidHeaderSpecific(pc,PC_CLASSID,1); 359 PetscValidPointer(ksp,2); 360 CHKERRQ(PetscTryMethod(pc,"PCDeflationGetCoarseKSP_C",(PC,KSP*),(pc,ksp))); 361 PetscFunctionReturn(0); 362 } 363 364 static PetscErrorCode PCDeflationGetPC_Deflation(PC pc,PC *apc) 365 { 366 PC_Deflation *def = (PC_Deflation*)pc->data; 367 368 PetscFunctionBegin; 369 *apc = def->pc; 370 PetscFunctionReturn(0); 371 } 372 373 /*@ 374 PCDeflationGetPC - Returns the additional preconditioner M^{-1}. 375 376 Not Collective 377 378 Input Parameters: 379 . pc - the preconditioner context 380 381 Output Parameters: 382 . apc - additional preconditioner 383 384 Level: advanced 385 386 .seealso: PCDEFLATION 387 @*/ 388 PetscErrorCode PCDeflationGetPC(PC pc,PC *apc) 389 { 390 PetscFunctionBegin; 391 PetscValidHeaderSpecific(pc,PC_CLASSID,1); 392 PetscValidPointer(pc,1); 393 CHKERRQ(PetscTryMethod(pc,"PCDeflationGetPC_C",(PC,PC*),(pc,apc))); 394 PetscFunctionReturn(0); 395 } 396 397 /* 398 x <- x + W*(W'*A*W)^{-1}*W'*r = x + Q*r 399 */ 400 static PetscErrorCode PCPreSolve_Deflation(PC pc,KSP ksp,Vec b, Vec x) 401 { 402 PC_Deflation *def = (PC_Deflation*)pc->data; 403 Mat A; 404 Vec r,w1,w2; 405 PetscBool nonzero; 406 407 PetscFunctionBegin; 408 w1 = def->workcoarse[0]; 409 w2 = def->workcoarse[1]; 410 r = def->work; 411 CHKERRQ(PCGetOperators(pc,NULL,&A)); 412 413 CHKERRQ(KSPGetInitialGuessNonzero(ksp,&nonzero)); 414 CHKERRQ(KSPSetInitialGuessNonzero(ksp,PETSC_TRUE)); 415 if (nonzero) { 416 CHKERRQ(MatMult(A,x,r)); /* r <- b - Ax */ 417 CHKERRQ(VecAYPX(r,-1.0,b)); 418 } else { 419 CHKERRQ(VecCopy(b,r)); /* r <- b (x is 0) */ 420 } 421 422 if (def->Wt) { 423 CHKERRQ(MatMult(def->Wt,r,w1)); /* w1 <- W'*r */ 424 } else { 425 CHKERRQ(MatMultHermitianTranspose(def->W,r,w1)); /* w1 <- W'*r */ 426 } 427 CHKERRQ(KSPSolve(def->WtAWinv,w1,w2)); /* w2 <- (W'*A*W)^{-1}*w1 */ 428 CHKERRQ(MatMult(def->W,w2,r)); /* r <- W*w2 */ 429 CHKERRQ(VecAYPX(x,1.0,r)); 430 PetscFunctionReturn(0); 431 } 432 433 /* 434 if (def->correct) { 435 z <- M^{-1}r - W*(W'*A*W)^{-1}*(W'*A*M^{-1}r - l*W'*r) = (P*M^{-1} + l*Q)*r 436 } else { 437 z <- M^{-1}*r - W*(W'*A*W)^{-1}*W'*A*M{-1}*r = P*M^{-1}*r 438 } 439 */ 440 static PetscErrorCode PCApply_Deflation(PC pc,Vec r,Vec z) 441 { 442 PC_Deflation *def = (PC_Deflation*)pc->data; 443 Mat A; 444 Vec u,w1,w2; 445 446 PetscFunctionBegin; 447 w1 = def->workcoarse[0]; 448 w2 = def->workcoarse[1]; 449 u = def->work; 450 CHKERRQ(PCGetOperators(pc,NULL,&A)); 451 452 CHKERRQ(PCApply(def->pc,r,z)); /* z <- M^{-1}*r */ 453 if (!def->init) { 454 CHKERRQ(MatMult(def->WtA,z,w1)); /* w1 <- W'*A*z */ 455 if (def->correct) { 456 if (def->Wt) { 457 CHKERRQ(MatMult(def->Wt,r,w2)); /* w2 <- W'*r */ 458 } else { 459 CHKERRQ(MatMultHermitianTranspose(def->W,r,w2)); /* w2 <- W'*r */ 460 } 461 CHKERRQ(VecAXPY(w1,-1.0*def->correctfact,w2)); /* w1 <- w1 - l*w2 */ 462 } 463 CHKERRQ(KSPSolve(def->WtAWinv,w1,w2)); /* w2 <- (W'*A*W)^{-1}*w1 */ 464 CHKERRQ(MatMult(def->W,w2,u)); /* u <- W*w2 */ 465 CHKERRQ(VecAXPY(z,-1.0,u)); /* z <- z - u */ 466 } 467 PetscFunctionReturn(0); 468 } 469 470 static PetscErrorCode PCSetUp_Deflation(PC pc) 471 { 472 PC_Deflation *def = (PC_Deflation*)pc->data; 473 KSP innerksp; 474 PC pcinner; 475 Mat Amat,nextDef=NULL,*mats; 476 PetscInt i,m,red,size; 477 PetscMPIInt commsize; 478 PetscBool match,flgspd,transp=PETSC_FALSE; 479 MatCompositeType ctype; 480 MPI_Comm comm; 481 char prefix[128]=""; 482 483 PetscFunctionBegin; 484 if (pc->setupcalled) PetscFunctionReturn(0); 485 CHKERRQ(PetscObjectGetComm((PetscObject)pc,&comm)); 486 CHKERRQ(PCGetOperators(pc,NULL,&Amat)); 487 if (!def->lvl && !def->prefix) { 488 CHKERRQ(PCGetOptionsPrefix(pc,&def->prefix)); 489 } 490 if (def->lvl) { 491 CHKERRQ(PetscSNPrintf(prefix,sizeof(prefix),"%d_",(int)def->lvl)); 492 } 493 494 /* compute a deflation space */ 495 if (def->W || def->Wt) { 496 def->spacetype = PC_DEFLATION_SPACE_USER; 497 } else { 498 CHKERRQ(PCDeflationComputeSpace(pc)); 499 } 500 501 /* nested deflation */ 502 if (def->W) { 503 CHKERRQ(PetscObjectTypeCompare((PetscObject)def->W,MATCOMPOSITE,&match)); 504 if (match) { 505 CHKERRQ(MatCompositeGetType(def->W,&ctype)); 506 CHKERRQ(MatCompositeGetNumberMat(def->W,&size)); 507 } 508 } else { 509 CHKERRQ(MatCreateHermitianTranspose(def->Wt,&def->W)); 510 CHKERRQ(PetscObjectTypeCompare((PetscObject)def->Wt,MATCOMPOSITE,&match)); 511 if (match) { 512 CHKERRQ(MatCompositeGetType(def->Wt,&ctype)); 513 CHKERRQ(MatCompositeGetNumberMat(def->Wt,&size)); 514 } 515 transp = PETSC_TRUE; 516 } 517 if (match && ctype == MAT_COMPOSITE_MULTIPLICATIVE) { 518 if (!transp) { 519 if (def->lvl < def->maxlvl) { 520 CHKERRQ(PetscMalloc1(size,&mats)); 521 for (i=0; i<size; i++) { 522 CHKERRQ(MatCompositeGetMat(def->W,i,&mats[i])); 523 } 524 size -= 1; 525 CHKERRQ(MatDestroy(&def->W)); 526 def->W = mats[size]; 527 CHKERRQ(PetscObjectReference((PetscObject)mats[size])); 528 if (size > 1) { 529 CHKERRQ(MatCreateComposite(comm,size,mats,&nextDef)); 530 CHKERRQ(MatCompositeSetType(nextDef,MAT_COMPOSITE_MULTIPLICATIVE)); 531 } else { 532 nextDef = mats[0]; 533 CHKERRQ(PetscObjectReference((PetscObject)mats[0])); 534 } 535 CHKERRQ(PetscFree(mats)); 536 } else { 537 /* TODO test merge side performance */ 538 /* CHKERRQ(MatCompositeSetMergeType(def->W,MAT_COMPOSITE_MERGE_LEFT)); */ 539 CHKERRQ(MatCompositeMerge(def->W)); 540 } 541 } else { 542 if (def->lvl < def->maxlvl) { 543 CHKERRQ(PetscMalloc1(size,&mats)); 544 for (i=0; i<size; i++) { 545 CHKERRQ(MatCompositeGetMat(def->Wt,i,&mats[i])); 546 } 547 size -= 1; 548 CHKERRQ(MatDestroy(&def->Wt)); 549 def->Wt = mats[0]; 550 CHKERRQ(PetscObjectReference((PetscObject)mats[0])); 551 if (size > 1) { 552 CHKERRQ(MatCreateComposite(comm,size,&mats[1],&nextDef)); 553 CHKERRQ(MatCompositeSetType(nextDef,MAT_COMPOSITE_MULTIPLICATIVE)); 554 } else { 555 nextDef = mats[1]; 556 CHKERRQ(PetscObjectReference((PetscObject)mats[1])); 557 } 558 CHKERRQ(PetscFree(mats)); 559 } else { 560 /* CHKERRQ(MatCompositeSetMergeType(def->W,MAT_COMPOSITE_MERGE_LEFT)); */ 561 CHKERRQ(MatCompositeMerge(def->Wt)); 562 } 563 } 564 } 565 566 if (transp) { 567 CHKERRQ(MatDestroy(&def->W)); 568 CHKERRQ(MatHermitianTranspose(def->Wt,MAT_INITIAL_MATRIX,&def->W)); 569 } 570 571 /* assemble WtA */ 572 if (!def->WtA) { 573 if (def->Wt) { 574 CHKERRQ(MatMatMult(def->Wt,Amat,MAT_INITIAL_MATRIX,PETSC_DEFAULT,&def->WtA)); 575 } else { 576 #if defined(PETSC_USE_COMPLEX) 577 CHKERRQ(MatHermitianTranspose(def->W,MAT_INITIAL_MATRIX,&def->Wt)); 578 CHKERRQ(MatMatMult(def->Wt,Amat,MAT_INITIAL_MATRIX,PETSC_DEFAULT,&def->WtA)); 579 #else 580 CHKERRQ(MatTransposeMatMult(def->W,Amat,MAT_INITIAL_MATRIX,PETSC_DEFAULT,&def->WtA)); 581 #endif 582 } 583 } 584 /* setup coarse problem */ 585 if (!def->WtAWinv) { 586 CHKERRQ(MatGetSize(def->W,NULL,&m)); 587 if (!def->WtAW) { 588 CHKERRQ(MatMatMult(def->WtA,def->W,MAT_INITIAL_MATRIX,PETSC_DEFAULT,&def->WtAW)); 589 /* TODO create MatInheritOption(Mat,MatOption) */ 590 CHKERRQ(MatGetOption(Amat,MAT_SPD,&flgspd)); 591 CHKERRQ(MatSetOption(def->WtAW,MAT_SPD,flgspd)); 592 if (PetscDefined(USE_DEBUG)) { 593 /* Check columns of W are not in kernel of A */ 594 PetscReal *norms; 595 CHKERRQ(PetscMalloc1(m,&norms)); 596 CHKERRQ(MatGetColumnNorms(def->WtAW,NORM_INFINITY,norms)); 597 for (i=0; i<m; i++) { 598 if (norms[i] < 100*PETSC_MACHINE_EPSILON) { 599 SETERRQ(comm,PETSC_ERR_SUP,"Column %D of W is in kernel of A.",i); 600 } 601 } 602 CHKERRQ(PetscFree(norms)); 603 } 604 } else { 605 CHKERRQ(MatGetOption(def->WtAW,MAT_SPD,&flgspd)); 606 } 607 /* TODO use MATINV ? */ 608 CHKERRQ(KSPCreate(comm,&def->WtAWinv)); 609 CHKERRQ(KSPSetOperators(def->WtAWinv,def->WtAW,def->WtAW)); 610 CHKERRQ(KSPGetPC(def->WtAWinv,&pcinner)); 611 /* Setup KSP and PC */ 612 if (nextDef) { /* next level for multilevel deflation */ 613 innerksp = def->WtAWinv; 614 /* set default KSPtype */ 615 if (!def->ksptype) { 616 def->ksptype = KSPFGMRES; 617 if (flgspd) { /* SPD system */ 618 def->ksptype = KSPFCG; 619 } 620 } 621 CHKERRQ(KSPSetType(innerksp,def->ksptype)); /* TODO iherit from KSP + tolerances */ 622 CHKERRQ(PCSetType(pcinner,PCDEFLATION)); /* TODO create coarse preconditinoner M_c = WtMW ? */ 623 CHKERRQ(PCDeflationSetSpace(pcinner,nextDef,transp)); 624 CHKERRQ(PCDeflationSetLevels_Deflation(pcinner,def->lvl+1,def->maxlvl)); 625 /* inherit options */ 626 if (def->prefix) ((PC_Deflation*)(pcinner->data))->prefix = def->prefix; 627 ((PC_Deflation*)(pcinner->data))->init = def->init; 628 ((PC_Deflation*)(pcinner->data))->ksptype = def->ksptype; 629 ((PC_Deflation*)(pcinner->data))->correct = def->correct; 630 ((PC_Deflation*)(pcinner->data))->correctfact = def->correctfact; 631 ((PC_Deflation*)(pcinner->data))->reductionfact = def->reductionfact; 632 CHKERRQ(MatDestroy(&nextDef)); 633 } else { /* the last level */ 634 CHKERRQ(KSPSetType(def->WtAWinv,KSPPREONLY)); 635 CHKERRQ(PCSetType(pcinner,PCTELESCOPE)); 636 /* do not overwrite PCTELESCOPE */ 637 if (def->prefix) { 638 CHKERRQ(KSPSetOptionsPrefix(def->WtAWinv,def->prefix)); 639 } 640 CHKERRQ(KSPAppendOptionsPrefix(def->WtAWinv,"deflation_tel_")); 641 CHKERRQ(PCSetFromOptions(pcinner)); 642 CHKERRQ(PetscObjectTypeCompare((PetscObject)pcinner,PCTELESCOPE,&match)); 643 PetscCheck(match,comm,PETSC_ERR_SUP,"User can not owerwrite PCTELESCOPE on bottom level, use reduction factor = 1 instead."); 644 /* Reduction factor choice */ 645 red = def->reductionfact; 646 if (red < 0) { 647 CHKERRMPI(MPI_Comm_size(comm,&commsize)); 648 red = PetscCeilInt(commsize,PetscCeilInt(m,commsize)); 649 CHKERRQ(PetscObjectTypeCompareAny((PetscObject)(def->WtAW),&match,MATSEQDENSE,MATMPIDENSE,MATDENSE,"")); 650 if (match) red = commsize; 651 CHKERRQ(PetscInfo(pc,"Auto choosing reduction factor %D\n",red)); 652 } 653 CHKERRQ(PCTelescopeSetReductionFactor(pcinner,red)); 654 CHKERRQ(PCSetUp(pcinner)); 655 CHKERRQ(PCTelescopeGetKSP(pcinner,&innerksp)); 656 if (innerksp) { 657 CHKERRQ(KSPGetPC(innerksp,&pcinner)); 658 CHKERRQ(PCSetType(pcinner,PCLU)); 659 #if defined(PETSC_HAVE_SUPERLU) 660 CHKERRQ(MatGetFactorAvailable(def->WtAW,MATSOLVERSUPERLU,MAT_FACTOR_LU,&match)); 661 if (match) { 662 CHKERRQ(PCFactorSetMatSolverType(pcinner,MATSOLVERSUPERLU)); 663 } 664 #endif 665 #if defined(PETSC_HAVE_SUPERLU_DIST) 666 CHKERRQ(MatGetFactorAvailable(def->WtAW,MATSOLVERSUPERLU_DIST,MAT_FACTOR_LU,&match)); 667 if (match) { 668 CHKERRQ(PCFactorSetMatSolverType(pcinner,MATSOLVERSUPERLU_DIST)); 669 } 670 #endif 671 } 672 } 673 674 if (innerksp) { 675 if (def->prefix) { 676 CHKERRQ(KSPSetOptionsPrefix(innerksp,def->prefix)); 677 CHKERRQ(KSPAppendOptionsPrefix(innerksp,"deflation_")); 678 } else { 679 CHKERRQ(KSPSetOptionsPrefix(innerksp,"deflation_")); 680 } 681 CHKERRQ(KSPAppendOptionsPrefix(innerksp,prefix)); 682 CHKERRQ(KSPSetFromOptions(innerksp)); 683 CHKERRQ(KSPSetUp(innerksp)); 684 } 685 } 686 CHKERRQ(KSPSetFromOptions(def->WtAWinv)); 687 CHKERRQ(KSPSetUp(def->WtAWinv)); 688 689 /* create preconditioner */ 690 if (!def->pc) { 691 CHKERRQ(PCCreate(comm,&def->pc)); 692 CHKERRQ(PCSetOperators(def->pc,Amat,Amat)); 693 CHKERRQ(PCSetType(def->pc,PCNONE)); 694 if (def->prefix) { 695 CHKERRQ(PCSetOptionsPrefix(def->pc,def->prefix)); 696 } 697 CHKERRQ(PCAppendOptionsPrefix(def->pc,"deflation_")); 698 CHKERRQ(PCAppendOptionsPrefix(def->pc,prefix)); 699 CHKERRQ(PCAppendOptionsPrefix(def->pc,"pc_")); 700 CHKERRQ(PCSetFromOptions(def->pc)); 701 CHKERRQ(PCSetUp(def->pc)); 702 } 703 704 /* create work vecs */ 705 CHKERRQ(MatCreateVecs(Amat,NULL,&def->work)); 706 CHKERRQ(KSPCreateVecs(def->WtAWinv,2,&def->workcoarse,0,NULL)); 707 PetscFunctionReturn(0); 708 } 709 710 static PetscErrorCode PCReset_Deflation(PC pc) 711 { 712 PC_Deflation *def = (PC_Deflation*)pc->data; 713 714 PetscFunctionBegin; 715 CHKERRQ(VecDestroy(&def->work)); 716 CHKERRQ(VecDestroyVecs(2,&def->workcoarse)); 717 CHKERRQ(MatDestroy(&def->W)); 718 CHKERRQ(MatDestroy(&def->Wt)); 719 CHKERRQ(MatDestroy(&def->WtA)); 720 CHKERRQ(MatDestroy(&def->WtAW)); 721 CHKERRQ(KSPDestroy(&def->WtAWinv)); 722 CHKERRQ(PCDestroy(&def->pc)); 723 PetscFunctionReturn(0); 724 } 725 726 static PetscErrorCode PCDestroy_Deflation(PC pc) 727 { 728 PetscFunctionBegin; 729 CHKERRQ(PCReset_Deflation(pc)); 730 CHKERRQ(PetscFree(pc->data)); 731 PetscFunctionReturn(0); 732 } 733 734 static PetscErrorCode PCView_Deflation(PC pc,PetscViewer viewer) 735 { 736 PC_Deflation *def = (PC_Deflation*)pc->data; 737 PetscInt its; 738 PetscBool iascii; 739 PetscErrorCode ierr; 740 741 PetscFunctionBegin; 742 CHKERRQ(PetscObjectTypeCompare((PetscObject)viewer,PETSCVIEWERASCII,&iascii)); 743 if (iascii) { 744 if (def->correct) { 745 ierr = PetscViewerASCIIPrintf(viewer,"using CP correction, factor = %g+%gi\n", 746 (double)PetscRealPart(def->correctfact), 747 (double)PetscImaginaryPart(def->correctfact));CHKERRQ(ierr); 748 } 749 if (!def->lvl) { 750 CHKERRQ(PetscViewerASCIIPrintf(viewer,"deflation space type: %s\n",PCDeflationSpaceTypes[def->spacetype])); 751 } 752 753 CHKERRQ(PetscViewerASCIIPrintf(viewer,"--- Additional PC:\n")); 754 CHKERRQ(PetscViewerASCIIPushTab(viewer)); 755 CHKERRQ(PCView(def->pc,viewer)); 756 CHKERRQ(PetscViewerASCIIPopTab(viewer)); 757 758 CHKERRQ(PetscViewerASCIIPrintf(viewer,"--- Coarse problem solver:\n")); 759 CHKERRQ(PetscViewerASCIIPushTab(viewer)); 760 CHKERRQ(KSPGetTotalIterations(def->WtAWinv,&its)); 761 CHKERRQ(PetscViewerASCIIPrintf(viewer,"total number of iterations: %D\n",its)); 762 CHKERRQ(KSPView(def->WtAWinv,viewer)); 763 CHKERRQ(PetscViewerASCIIPopTab(viewer)); 764 } 765 PetscFunctionReturn(0); 766 } 767 768 static PetscErrorCode PCSetFromOptions_Deflation(PetscOptionItems *PetscOptionsObject,PC pc) 769 { 770 PC_Deflation *def = (PC_Deflation*)pc->data; 771 772 PetscFunctionBegin; 773 CHKERRQ(PetscOptionsHead(PetscOptionsObject,"Deflation options")); 774 CHKERRQ(PetscOptionsBool("-pc_deflation_init_only","Use only initialization step - Initdef","PCDeflationSetInitOnly",def->init,&def->init,NULL)); 775 CHKERRQ(PetscOptionsInt("-pc_deflation_levels","Maximum of deflation levels","PCDeflationSetLevels",def->maxlvl,&def->maxlvl,NULL)); 776 CHKERRQ(PetscOptionsInt("-pc_deflation_reduction_factor","Reduction factor for coarse problem solution using PCTELESCOPE","PCDeflationSetReductionFactor",def->reductionfact,&def->reductionfact,NULL)); 777 CHKERRQ(PetscOptionsBool("-pc_deflation_correction","Add coarse problem correction Q to P","PCDeflationSetCorrectionFactor",def->correct,&def->correct,NULL)); 778 CHKERRQ(PetscOptionsScalar("-pc_deflation_correction_factor","Set multiple of Q to use as coarse problem correction","PCDeflationSetCorrectionFactor",def->correctfact,&def->correctfact,NULL)); 779 CHKERRQ(PetscOptionsEnum("-pc_deflation_compute_space","Compute deflation space","PCDeflationSetSpace",PCDeflationSpaceTypes,(PetscEnum)def->spacetype,(PetscEnum*)&def->spacetype,NULL)); 780 CHKERRQ(PetscOptionsInt("-pc_deflation_compute_space_size","Set size of the deflation space to compute","PCDeflationSetSpace",def->spacesize,&def->spacesize,NULL)); 781 CHKERRQ(PetscOptionsBool("-pc_deflation_space_extend","Extend deflation space instead of truncating (wavelets)","PCDeflation",def->extendsp,&def->extendsp,NULL)); 782 CHKERRQ(PetscOptionsTail()); 783 PetscFunctionReturn(0); 784 } 785 786 /*MC 787 PCDEFLATION - Deflation preconditioner shifts (deflates) part of the spectrum to zero or to a predefined value. 788 789 Options Database Keys: 790 + -pc_deflation_init_only <false> - if true computes only the special guess 791 . -pc_deflation_max_lvl <0> - maximum number of levels for multilevel deflation 792 . -pc_deflation_reduction_factor <\-1> - reduction factor on bottom level coarse problem for PCTELESCOPE (default based on the size of the coarse problem) 793 . -pc_deflation_correction <false> - if true apply coarse problem correction 794 . -pc_deflation_correction_factor <1.0> - sets coarse problem correction factor 795 . -pc_deflation_compute_space <haar> - compute PCDeflationSpaceType deflation space 796 - -pc_deflation_compute_space_size <1> - size of the deflation space (corresponds to number of levels for wavelet-based deflation) 797 798 Notes: 799 Given a (complex - transpose is always Hermitian) full rank deflation matrix W, the deflation (introduced in [1,2]) 800 preconditioner uses projections Q = W*(W'*A*W)^{-1}*W' and P = I - Q*A, where A is pmat. 801 802 The deflation computes initial guess x0 = x_{-1} - Q*r_{-1}, which is the solution on the deflation space. 803 If PCDeflationSetInitOnly() or -pc_deflation_init_only is set to PETSC_TRUE (InitDef scheme), the application of the 804 preconditioner consists only of application of the additional preconditioner M^{-1}. Otherwise, the preconditioner 805 application consists of P*M^{-1} + factor*Q. The first part of the preconditioner (PM^{-1}) shifts some eigenvalues 806 to zero while the addition of the coarse problem correction (factor*Q) makes the preconditioner to shift some 807 eigenvalues to the given factor. The InitDef scheme is recommended for deflation using high accuracy estimates 808 of eigenvectors of A when it exhibits similar convergence to the full deflation but is cheaper. 809 810 The deflation matrix is by default automatically computed. The type of deflation matrix and its size to compute can 811 be controlled by PCDeflationSetSpaceToCompute() or -pc_deflation_compute_space and -pc_deflation_compute_space_size. 812 User can set an arbitrary deflation space matrix with PCDeflationSetSpace(). If the deflation matrix 813 is a multiplicative MATCOMPOSITE, a multilevel deflation [3] is used. The first matrix in the composite is used as the 814 deflation matrix, and the coarse problem (W'*A*W)^{-1} is solved by KSPFCG (if A is MAT_SPD) or KSPFGMRES preconditioned 815 by deflation with deflation matrix being the next matrix in the MATCOMPOSITE. This scheme repeats until the maximum 816 level is reached or there are no more matrices. If the maximum level is reached, the remaining matrices are merged 817 (multiplied) to create the last deflation matrix. The maximum level defaults to 0 and can be set by 818 PCDeflationSetLevels() or by -pc_deflation_levels. 819 820 The coarse problem KSP can be controlled from the command line with prefix -deflation_ for the first level and -deflation_[lvl-1] 821 from the second level onward. You can also use 822 PCDeflationGetCoarseKSP() to control it from code. The bottom level KSP defaults to 823 KSPPREONLY with PCLU direct solver (MATSOLVERSUPERLU/MATSOLVERSUPERLU_DIST if available) wrapped into PCTELESCOPE. 824 For convenience, the reduction factor can be set by PCDeflationSetReductionFactor() 825 or -pc_deflation_recduction_factor. The default is chosen heuristically based on the coarse problem size. 826 827 The additional preconditioner can be controlled from command line with prefix -deflation_[lvl]_pc (same rules used for 828 coarse problem KSP apply for [lvl]_ part of prefix), e.g., -deflation_1_pc_pc_type bjacobi. You can also use 829 PCDeflationGetPC() to control the additional preconditioner from code. It defaults to PCNONE. 830 831 The coarse problem correction term (factor*Q) can be turned on by -pc_deflation_correction and the factor value can 832 be set by pc_deflation_correction_factor or by PCDeflationSetCorrectionFactor(). The coarse problem can 833 significantly improve convergence when the deflation coarse problem is not solved with high enough accuracy. We 834 recommend setting factor to some eigenvalue, e.g., the largest eigenvalue so that the preconditioner does not create 835 an isolated eigenvalue. 836 837 The options are automatically inherited from the previous deflation level. 838 839 The preconditioner supports KSPMonitorDynamicTolerance(). This is useful for the multilevel scheme for which we also 840 recommend limiting the number of iterations for the coarse problems. 841 842 See section 3 of [4] for additional references and decription of the algorithm when used for conjugate gradients. 843 Section 4 describes some possible choices for the deflation space. 844 845 Developer Notes: 846 Contributed by Jakub Kruzik (PERMON), Institute of Geonics of the Czech 847 Academy of Sciences and VSB - TU Ostrava. 848 849 Developed from PERMON code used in [4] while on a research stay with 850 Prof. Reinhard Nabben at the Institute of Mathematics, TU Berlin. 851 852 References: 853 + * - A. Nicolaides. "Deflation of conjugate gradients with applications to boundary value problems", SIAM J. Numer. Anal. 24.2, 1987. 854 . * - Z. Dostal. "Conjugate gradient method with preconditioning by projector", Int J. Comput. Math. 23.3-4, 1988. 855 . * - Y. A. Erlangga and R. Nabben. "Multilevel Projection-Based Nested Krylov Iteration for Boundary Value Problems", SIAM J. Sci. Comput. 30.3, 2008. 856 - * - J. Kruzik "Implementation of the Deflated Variants of the Conjugate Gradient Method", Master's thesis, VSB-TUO, 2018 - http://dspace5.vsb.cz/bitstream/handle/10084/130303/KRU0097_USP_N2658_2612T078_2018.pdf 857 858 Level: intermediate 859 860 .seealso: PCCreate(), PCSetType(), PCType (for list of available types), PC, 861 PCDeflationSetInitOnly(), PCDeflationSetLevels(), PCDeflationSetReductionFactor(), 862 PCDeflationSetCorrectionFactor(), PCDeflationSetSpaceToCompute(), 863 PCDeflationSetSpace(), PCDeflationSpaceType, PCDeflationSetProjectionNullSpaceMat(), 864 PCDeflationSetCoarseMat(), PCDeflationGetCoarseKSP(), PCDeflationGetPC() 865 M*/ 866 867 PETSC_EXTERN PetscErrorCode PCCreate_Deflation(PC pc) 868 { 869 PC_Deflation *def; 870 871 PetscFunctionBegin; 872 CHKERRQ(PetscNewLog(pc,&def)); 873 pc->data = (void*)def; 874 875 def->init = PETSC_FALSE; 876 def->correct = PETSC_FALSE; 877 def->correctfact = 1.0; 878 def->reductionfact = -1; 879 def->spacetype = PC_DEFLATION_SPACE_HAAR; 880 def->spacesize = 1; 881 def->extendsp = PETSC_FALSE; 882 def->lvl = 0; 883 def->maxlvl = 0; 884 def->W = NULL; 885 def->Wt = NULL; 886 887 pc->ops->apply = PCApply_Deflation; 888 pc->ops->presolve = PCPreSolve_Deflation; 889 pc->ops->setup = PCSetUp_Deflation; 890 pc->ops->reset = PCReset_Deflation; 891 pc->ops->destroy = PCDestroy_Deflation; 892 pc->ops->setfromoptions = PCSetFromOptions_Deflation; 893 pc->ops->view = PCView_Deflation; 894 895 CHKERRQ(PetscObjectComposeFunction((PetscObject)pc,"PCDeflationSetInitOnly_C",PCDeflationSetInitOnly_Deflation)); 896 CHKERRQ(PetscObjectComposeFunction((PetscObject)pc,"PCDeflationSetLevels_C",PCDeflationSetLevels_Deflation)); 897 CHKERRQ(PetscObjectComposeFunction((PetscObject)pc,"PCDeflationSetReductionFactor_C",PCDeflationSetReductionFactor_Deflation)); 898 CHKERRQ(PetscObjectComposeFunction((PetscObject)pc,"PCDeflationSetCorrectionFactor_C",PCDeflationSetCorrectionFactor_Deflation)); 899 CHKERRQ(PetscObjectComposeFunction((PetscObject)pc,"PCDeflationSetSpaceToCompute_C",PCDeflationSetSpaceToCompute_Deflation)); 900 CHKERRQ(PetscObjectComposeFunction((PetscObject)pc,"PCDeflationSetSpace_C",PCDeflationSetSpace_Deflation)); 901 CHKERRQ(PetscObjectComposeFunction((PetscObject)pc,"PCDeflationSetProjectionNullSpaceMat_C",PCDeflationSetProjectionNullSpaceMat_Deflation)); 902 CHKERRQ(PetscObjectComposeFunction((PetscObject)pc,"PCDeflationSetCoarseMat_C",PCDeflationSetCoarseMat_Deflation)); 903 CHKERRQ(PetscObjectComposeFunction((PetscObject)pc,"PCDeflationGetCoarseKSP_C",PCDeflationGetCoarseKSP_Deflation)); 904 CHKERRQ(PetscObjectComposeFunction((PetscObject)pc,"PCDeflationGetPC_C",PCDeflationGetPC_Deflation)); 905 PetscFunctionReturn(0); 906 } 907