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