1 #include <../src/ksp/pc/impls/deflation/deflation.h> /*I "petscpc.h" I*/ /* includes for fortran wrappers */ 2 3 const char *const PCDeflationSpaceTypes[] = { 4 "haar", 5 "jacket-haar", 6 "db2", 7 "db4", 8 "db8", 9 "db16", 10 "biorth22", 11 "meyer", 12 "aggregation", 13 "slepc", 14 "slepc-cheap", 15 "user", 16 "PCDeflationSpaceType", 17 "PC_DEFLATION_SPACE_", 18 0 19 }; 20 21 static PetscErrorCode PCDeflationSetInitOnly_Deflation(PC pc,PetscBool flg) 22 { 23 PC_Deflation *def = (PC_Deflation*)pc->data; 24 25 PetscFunctionBegin; 26 def->init = flg; 27 PetscFunctionReturn(0); 28 } 29 30 /*@ 31 PCDeflationSetInitOnly - Do only initialization step. 32 Sets initial guess to the solution on the deflation space but do not apply deflation preconditioner. 33 The additional preconditioner is still applied. 34 35 Logically Collective on PC 36 37 Input Parameters: 38 + pc - the preconditioner context 39 - flg - default PETSC_FALSE 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 PCDeflationSetLvl_Deflation(PC pc,PetscInt current,PetscInt max) 58 { 59 PC_Deflation *def = (PC_Deflation*)pc->data; 60 61 PetscFunctionBegin; 62 if (current) def->nestedlvl = current; 63 def->maxnestedlvl = max; 64 PetscFunctionReturn(0); 65 } 66 67 /*@ 68 PCDeflationSetMaxLvl - Set maximum level of deflation. 69 70 Logically Collective on PC 71 72 Input Parameters: 73 + pc - the preconditioner context 74 - max - maximum deflation level 75 76 Level: intermediate 77 78 .seealso: PCDEFLATION 79 @*/ 80 PetscErrorCode PCDeflationSetMaxLvl(PC pc,PetscInt max) 81 { 82 PetscErrorCode ierr; 83 84 PetscFunctionBegin; 85 PetscValidHeaderSpecific(pc,PC_CLASSID,1); 86 PetscValidLogicalCollectiveInt(pc,max,2); 87 ierr = PetscTryMethod(pc,"PCDeflationSetLvl_C",(PC,PetscInt,PetscInt),(pc,0,max));CHKERRQ(ierr); 88 PetscFunctionReturn(0); 89 } 90 91 static PetscErrorCode PCDeflationSetReductionFactor_Deflation(PC pc,PetscInt red) 92 { 93 PC_Deflation *def = (PC_Deflation*)pc->data; 94 95 PetscFunctionBegin; 96 def->reductionfact = red; 97 PetscFunctionReturn(0); 98 } 99 100 /*@ 101 PCDeflationSetReductionFactor - Set reduction factor for PCTELESCOPE coarse problem solver. 102 103 Logically Collective on PC 104 105 Input Parameters: 106 + pc - the preconditioner context 107 - red - reduction factor (or PETSC_DETERMINE) 108 109 Level: intermediate 110 111 .seealso: PCDEFLATION 112 @*/ 113 PetscErrorCode PCDeflationSetReductionFactor(PC pc,PetscInt red) 114 { 115 PetscErrorCode ierr; 116 117 PetscFunctionBegin; 118 PetscValidHeaderSpecific(pc,PC_CLASSID,1); 119 PetscValidLogicalCollectiveInt(pc,red,2); 120 ierr = PetscTryMethod(pc,"PCDeflationSetReductionFactor_C",(PC,PetscInt),(pc,red));CHKERRQ(ierr); 121 PetscFunctionReturn(0); 122 } 123 124 static PetscErrorCode PCDeflationSetCorrectionFactor_Deflation(PC pc,PetscScalar fact) 125 { 126 PC_Deflation *def = (PC_Deflation*)pc->data; 127 128 PetscFunctionBegin; 129 /* TODO PETSC_DETERMINE -> compute max eigenvalue with power method */ 130 def->correct = PETSC_TRUE; 131 def->correctfact = fact; 132 if (fact == PETSC_DEFAULT) { 133 def->correctfact = 1.0; 134 } else 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} + factor*Q. 143 144 Logically Collective on PC 145 146 Input Parameters: 147 + pc - the preconditioner context 148 - fact - correction factor (set 0.0 to disable, PETSC_DEFAULT = 1.0) 149 150 Level: intermediate 151 152 .seealso: PCDEFLATION 153 @*/ 154 PetscErrorCode PCDeflationSetCorrectionFactor(PC pc,PetscScalar fact) 155 { 156 PetscErrorCode ierr; 157 158 PetscFunctionBegin; 159 PetscValidHeaderSpecific(pc,PC_CLASSID,1); 160 PetscValidLogicalCollectiveScalar(pc,fact,2); 161 ierr = PetscTryMethod(pc,"PCDeflationSetCorrectionFactor_C",(PC,PetscScalar),(pc,fact));CHKERRQ(ierr); 162 PetscFunctionReturn(0); 163 } 164 165 static PetscErrorCode PCDeflationSetSpaceToCompute_Deflation(PC pc,PCDeflationSpaceType type,PetscInt size) 166 { 167 PC_Deflation *def = (PC_Deflation*)pc->data; 168 169 PetscFunctionBegin; 170 if (type) def->spacetype = type; 171 if (size > 0) def->spacesize = size; 172 PetscFunctionReturn(0); 173 } 174 175 /*@ 176 PCDeflationSetSpaceToCompute - Set deflation space type and size to compute. 177 178 Logically Collective on PC 179 180 Input Parameters: 181 + pc - the preconditioner context 182 . type - deflation space type to compute (or PETSC_IGNORE) 183 - size - size of the space to compute (or PETSC_DEFAULT) 184 185 Notes: 186 For wavelet-based deflation, size represents number of levels. 187 The deflation space is computed in PCSetUP(). 188 189 Level: intermediate 190 191 .seealso: PCDEFLATION 192 @*/ 193 PetscErrorCode PCDeflationSetSpaceToCompute(PC pc,PCDeflationSpaceType type,PetscInt size) 194 { 195 PetscErrorCode ierr; 196 197 PetscFunctionBegin; 198 PetscValidHeaderSpecific(pc,PC_CLASSID,1); 199 if (type) PetscValidLogicalCollectiveEnum(pc,type,2); 200 if (size > 0) PetscValidLogicalCollectiveInt(pc,size,3); 201 ierr = PetscTryMethod(pc,"PCDeflationSetSpaceToCompute_C",(PC,PCDeflationSpaceType,PetscInt),(pc,type,size));CHKERRQ(ierr); 202 PetscFunctionReturn(0); 203 } 204 205 static PetscErrorCode PCDeflationSetSpace_Deflation(PC pc,Mat W,PetscBool transpose) 206 { 207 PC_Deflation *def = (PC_Deflation*)pc->data; 208 PetscErrorCode ierr; 209 210 PetscFunctionBegin; 211 if (transpose) { 212 def->Wt = W; 213 def->W = NULL; 214 } else { 215 def->W = W; 216 } 217 ierr = PetscObjectReference((PetscObject)W);CHKERRQ(ierr); 218 PetscFunctionReturn(0); 219 } 220 221 /*@ 222 PCDeflationSetSpace - Set deflation space matrix (or its transpose). 223 224 Logically Collective on PC 225 226 Input Parameters: 227 + pc - the preconditioner context 228 . W - deflation matrix 229 - tranpose - indicates that W is an explicit transpose of the deflation matrix 230 231 Level: intermediate 232 233 .seealso: PCDEFLATION 234 @*/ 235 PetscErrorCode PCDeflationSetSpace(PC pc,Mat W,PetscBool transpose) 236 { 237 PetscErrorCode ierr; 238 239 PetscFunctionBegin; 240 PetscValidHeaderSpecific(pc,PC_CLASSID,1); 241 PetscValidHeaderSpecific(W,MAT_CLASSID,2); 242 PetscValidLogicalCollectiveBool(pc,transpose,3); 243 ierr = PetscTryMethod(pc,"PCDeflationSetSpace_C",(PC,Mat,PetscBool),(pc,W,transpose));CHKERRQ(ierr); 244 PetscFunctionReturn(0); 245 } 246 247 static PetscErrorCode PCDeflationSetProjectionNullSpaceMat_Deflation(PC pc,Mat mat) 248 { 249 PC_Deflation *def = (PC_Deflation*)pc->data; 250 PetscErrorCode ierr; 251 252 PetscFunctionBegin; 253 ierr = MatDestroy(&def->WtA);CHKERRQ(ierr); 254 def->WtA = mat; 255 ierr = PetscObjectReference((PetscObject)mat);CHKERRQ(ierr); 256 ierr = PetscLogObjectParent((PetscObject)pc,(PetscObject)def->WtA);CHKERRQ(ierr); 257 PetscFunctionReturn(0); 258 } 259 260 /*@ 261 PCDeflationSetProjectionNullSpaceMat - Set projection null space matrix (W'*A). 262 263 Not Collective 264 265 Input Parameters: 266 + pc - preconditioner context 267 - mat - projection null space matrix 268 269 Level: developer 270 271 .seealso: PCDEFLATION 272 @*/ 273 PetscErrorCode PCDeflationSetProjectionNullSpaceMat(PC pc,Mat mat) 274 { 275 PetscErrorCode ierr; 276 277 PetscFunctionBegin; 278 PetscValidHeaderSpecific(pc,PC_CLASSID,1); 279 PetscValidHeaderSpecific(mat,MAT_CLASSID,2); 280 ierr = PetscTryMethod(pc,"PCDeflationSetProjectionNullSpaceMat_C",(PC,Mat),(pc,mat));CHKERRQ(ierr); 281 PetscFunctionReturn(0); 282 } 283 284 static PetscErrorCode PCDeflationSetCoarseMat_Deflation(PC pc,Mat mat) 285 { 286 PC_Deflation *def = (PC_Deflation*)pc->data; 287 PetscErrorCode ierr; 288 289 PetscFunctionBegin; 290 ierr = MatDestroy(&def->WtAW);CHKERRQ(ierr); 291 def->WtAW = mat; 292 ierr = PetscObjectReference((PetscObject)mat);CHKERRQ(ierr); 293 ierr = PetscLogObjectParent((PetscObject)pc,(PetscObject)def->WtAW);CHKERRQ(ierr); 294 PetscFunctionReturn(0); 295 } 296 297 /*@ 298 PCDeflationSetCoarseMat - Set coarse problem Mat. 299 300 Not Collective 301 302 Input Parameters: 303 + pc - preconditioner context 304 - mat - coarse problem mat 305 306 Level: developer 307 308 .seealso: PCDEFLATION 309 @*/ 310 PetscErrorCode PCDeflationSetCoarseMat(PC pc,Mat mat) 311 { 312 PetscErrorCode ierr; 313 314 PetscFunctionBegin; 315 PetscValidHeaderSpecific(pc,PC_CLASSID,1); 316 PetscValidHeaderSpecific(mat,MAT_CLASSID,2); 317 ierr = PetscTryMethod(pc,"PCDeflationSetCoarseMat_C",(PC,Mat),(pc,mat));CHKERRQ(ierr); 318 PetscFunctionReturn(0); 319 } 320 321 static PetscErrorCode PCDeflationGetCoarseKSP_Deflation(PC pc,KSP *ksp) 322 { 323 PC_Deflation *def = (PC_Deflation*)pc->data; 324 325 PetscFunctionBegin; 326 *ksp = def->WtAWinv; 327 PetscFunctionReturn(0); 328 } 329 330 /*@ 331 PCDeflationGetCoarseKSP - Returns a pointer to the coarse problem KSP. 332 333 Not Collective 334 335 Input Parameters: 336 . pc - preconditioner context 337 338 Output Parameter: 339 . ksp - coarse problem KSP context 340 341 Level: developer 342 343 .seealso: PCDeflationSetCoarseKSP(), PCDEFLATION 344 @*/ 345 PetscErrorCode PCDeflationGetCoarseKSP(PC pc,KSP *ksp) 346 { 347 PetscErrorCode ierr; 348 349 PetscFunctionBegin; 350 PetscValidHeaderSpecific(pc,PC_CLASSID,1); 351 PetscValidPointer(ksp,2); 352 ierr = PetscTryMethod(pc,"PCDeflationGetCoarseKSP_C",(PC,KSP*),(pc,ksp));CHKERRQ(ierr); 353 PetscFunctionReturn(0); 354 } 355 356 static PetscErrorCode PCDeflationSetCoarseKSP_Deflation(PC pc,KSP ksp) 357 { 358 PC_Deflation *def = (PC_Deflation*)pc->data; 359 PetscErrorCode ierr; 360 361 PetscFunctionBegin; 362 ierr = KSPDestroy(&def->WtAWinv);CHKERRQ(ierr); 363 def->WtAWinv = ksp; 364 ierr = PetscObjectReference((PetscObject)ksp);CHKERRQ(ierr); 365 ierr = PetscLogObjectParent((PetscObject)pc,(PetscObject)def->WtAWinv);CHKERRQ(ierr); 366 PetscFunctionReturn(0); 367 } 368 369 /*@ 370 PCDeflationSetCoarseKSP - Set coarse problem KSP. 371 372 Collective on PC 373 374 Input Parameters: 375 + pc - preconditioner context 376 - ksp - coarse problem KSP context 377 378 Level: developer 379 380 .seealso: PCDeflationGetCoarseKSP(), PCDEFLATION 381 @*/ 382 PetscErrorCode PCDeflationSetCoarseKSP(PC pc,KSP ksp) 383 { 384 PetscErrorCode ierr; 385 386 PetscFunctionBegin; 387 PetscValidHeaderSpecific(pc,PC_CLASSID,1); 388 PetscValidHeaderSpecific(ksp,KSP_CLASSID,2); 389 PetscCheckSameComm(pc,1,ksp,2); 390 ierr = PetscTryMethod(pc,"PCDeflationSetCoarseKSP_C",(PC,KSP),(pc,ksp));CHKERRQ(ierr); 391 PetscFunctionReturn(0); 392 } 393 394 static PetscErrorCode PCDeflationGetPC_Deflation(PC pc,PC *apc) 395 { 396 PC_Deflation *def = (PC_Deflation*)pc->data; 397 398 PetscFunctionBegin; 399 *apc = def->pc; 400 PetscFunctionReturn(0); 401 } 402 403 /*@ 404 PCDeflationGetPC - Returns a pointer to additional preconditioner. 405 406 Not Collective 407 408 Input Parameters: 409 . pc - the preconditioner context 410 411 Output Parameter: 412 . apc - additional preconditioner 413 414 Level: advanced 415 416 .seealso: PCDeflationSetPC(), PCDEFLATION 417 @*/ 418 PetscErrorCode PCDeflationGetPC(PC pc,PC *apc) 419 { 420 PetscErrorCode ierr; 421 422 PetscFunctionBegin; 423 PetscValidHeaderSpecific(pc,PC_CLASSID,1); 424 PetscValidPointer(pc,2); 425 ierr = PetscTryMethod(pc,"PCDeflationGetPC_C",(PC,PC*),(pc,apc));CHKERRQ(ierr); 426 PetscFunctionReturn(0); 427 } 428 429 static PetscErrorCode PCDeflationSetPC_Deflation(PC pc,PC apc) 430 { 431 PC_Deflation *def = (PC_Deflation*)pc->data; 432 PetscErrorCode ierr; 433 434 PetscFunctionBegin; 435 ierr = PCDestroy(&def->pc);CHKERRQ(ierr); 436 def->pc = apc; 437 ierr = PetscObjectReference((PetscObject)apc);CHKERRQ(ierr); 438 ierr = PetscLogObjectParent((PetscObject)pc,(PetscObject)def->pc);CHKERRQ(ierr); 439 PetscFunctionReturn(0); 440 } 441 442 /*@ 443 PCDeflationSetPC - Set additional preconditioner. 444 445 Collective on PC 446 447 Input Parameters: 448 + pc - the preconditioner context 449 - apc - additional preconditioner 450 451 Level: developer 452 453 .seealso: PCDeflationGetPC(), PCDEFLATION 454 @*/ 455 PetscErrorCode PCDeflationSetPC(PC pc,PC apc) 456 { 457 PetscErrorCode ierr; 458 459 PetscFunctionBegin; 460 PetscValidHeaderSpecific(pc,PC_CLASSID,1); 461 PetscValidHeaderSpecific(apc,PC_CLASSID,2); 462 PetscCheckSameComm(pc,1,apc,2); 463 ierr = PetscTryMethod(pc,"PCDeflationSetPC_C",(PC,PC),(pc,apc));CHKERRQ(ierr); 464 PetscFunctionReturn(0); 465 } 466 467 /* 468 x <- x + W*(W'*A*W)^{-1}*W'*r = x + Q*r 469 */ 470 static PetscErrorCode PCPreSolve_Deflation(PC pc,KSP ksp,Vec b, Vec x) 471 { 472 PC_Deflation *def = (PC_Deflation*)pc->data; 473 Mat A; 474 Vec r,w1,w2; 475 PetscBool nonzero; 476 PetscErrorCode ierr; 477 478 PetscFunctionBegin; 479 w1 = def->workcoarse[0]; 480 w2 = def->workcoarse[1]; 481 r = def->work; 482 ierr = PCGetOperators(pc,NULL,&A);CHKERRQ(ierr); 483 484 ierr = KSPGetInitialGuessNonzero(ksp,&nonzero);CHKERRQ(ierr); 485 ierr = KSPSetInitialGuessNonzero(ksp,PETSC_TRUE);CHKERRQ(ierr); 486 if (nonzero) { 487 ierr = MatMult(A,x,r);CHKERRQ(ierr); /* r <- b - Ax */ 488 ierr = VecAYPX(r,-1.0,b);CHKERRQ(ierr); 489 } else { 490 ierr = VecCopy(b,r);CHKERRQ(ierr); /* r <- b (x is 0) */ 491 } 492 493 if (def->Wt) { 494 ierr = MatMult(def->Wt,r,w1);CHKERRQ(ierr); /* w1 <- W'*r */ 495 } else { 496 ierr = MatMultHermitianTranspose(def->W,r,w1);CHKERRQ(ierr); /* w1 <- W'*r */ 497 } 498 ierr = KSPSolve(def->WtAWinv,w1,w2);CHKERRQ(ierr); /* w2 <- (W'*A*W)^{-1}*w1 */ 499 ierr = MatMult(def->W,w2,r);CHKERRQ(ierr); /* r <- W*w2 */ 500 ierr = VecAYPX(x,1.0,r);CHKERRQ(ierr); 501 PetscFunctionReturn(0); 502 } 503 504 /* 505 if (def->correct) { 506 z <- M^{-1}r - W*(W'*A*W)^{-1}*(W'*A*M^{-1}r - l*W'*r) = (P*M^{-1} + l*Q)*r 507 } else { 508 z <- M^{-1}*r - W*(W'*A*W)^{-1}*W'*A*M{-1}*r = P*M^{-1}*r 509 } 510 */ 511 static PetscErrorCode PCApply_Deflation(PC pc,Vec r,Vec z) 512 { 513 PC_Deflation *def = (PC_Deflation*)pc->data; 514 Mat A; 515 Vec u,w1,w2; 516 PetscErrorCode ierr; 517 518 PetscFunctionBegin; 519 w1 = def->workcoarse[0]; 520 w2 = def->workcoarse[1]; 521 u = def->work; 522 ierr = PCGetOperators(pc,NULL,&A);CHKERRQ(ierr); 523 524 ierr = PCApply(def->pc,r,z);CHKERRQ(ierr); /* z <- M^{-1}*r */ 525 if (!def->init) { 526 ierr = MatMult(def->WtA,z,w1);CHKERRQ(ierr); /* w1 <- W'*A*z */ 527 if (def->correct) { 528 if (def->Wt) { 529 ierr = MatMult(def->Wt,r,w2);CHKERRQ(ierr); /* w2 <- W'*r */ 530 } else { 531 ierr = MatMultHermitianTranspose(def->W,r,w2);CHKERRQ(ierr); /* w2 <- W'*r */ 532 } 533 ierr = VecAXPY(w1,-1.0*def->correctfact,w2);CHKERRQ(ierr); /* w1 <- w1 - l*w2 */ 534 } 535 ierr = KSPSolve(def->WtAWinv,w1,w2);CHKERRQ(ierr); /* w2 <- (W'*A*W)^{-1}*w1 */ 536 ierr = MatMult(def->W,w2,u);CHKERRQ(ierr); /* u <- W*w2 */ 537 ierr = VecAXPY(z,-1.0,u);CHKERRQ(ierr); /* z <- z - u */ 538 } 539 PetscFunctionReturn(0); 540 } 541 542 static PetscErrorCode PCSetUp_Deflation(PC pc) 543 { 544 PC_Deflation *def = (PC_Deflation*)pc->data; 545 KSP innerksp; 546 PC pcinner; 547 Mat Amat,nextDef=NULL,*mats; 548 PetscInt i,m,red,size,commsize; 549 PetscBool match,flgspd,transp=PETSC_FALSE; 550 MatCompositeType ctype; 551 MPI_Comm comm; 552 const char *prefix; 553 PetscErrorCode ierr; 554 555 PetscFunctionBegin; 556 if (pc->setupcalled) PetscFunctionReturn(0); 557 ierr = PetscObjectGetComm((PetscObject)pc,&comm);CHKERRQ(ierr); 558 ierr = PCGetOperators(pc,NULL,&Amat);CHKERRQ(ierr); 559 ierr = PCGetOptionsPrefix(pc,&prefix);CHKERRQ(ierr); 560 561 /* compute a deflation space */ 562 if (def->W || def->Wt) { 563 def->spacetype = PC_DEFLATION_SPACE_USER; 564 } else { 565 ierr = PCDeflationComputeSpace(pc);CHKERRQ(ierr); 566 } 567 568 /* nested deflation */ 569 if (def->W) { 570 ierr = PetscObjectTypeCompare((PetscObject)def->W,MATCOMPOSITE,&match);CHKERRQ(ierr); 571 if (match) { 572 ierr = MatCompositeGetType(def->W,&ctype);CHKERRQ(ierr); 573 ierr = MatCompositeGetNumberMat(def->W,&size);CHKERRQ(ierr); 574 } 575 } else { 576 ierr = MatCreateHermitianTranspose(def->Wt,&def->W);CHKERRQ(ierr); 577 ierr = PetscObjectTypeCompare((PetscObject)def->Wt,MATCOMPOSITE,&match);CHKERRQ(ierr); 578 if (match) { 579 ierr = MatCompositeGetType(def->Wt,&ctype);CHKERRQ(ierr); 580 ierr = MatCompositeGetNumberMat(def->Wt,&size);CHKERRQ(ierr); 581 } 582 transp = PETSC_TRUE; 583 } 584 if (match && ctype == MAT_COMPOSITE_MULTIPLICATIVE) { 585 if (!transp) { 586 if (def->nestedlvl < def->maxnestedlvl) { 587 ierr = PetscMalloc1(size,&mats);CHKERRQ(ierr); 588 for (i=0; i<size; i++) { 589 ierr = MatCompositeGetMat(def->W,i,&mats[i]);CHKERRQ(ierr); 590 } 591 size -= 1; 592 ierr = MatDestroy(&def->W);CHKERRQ(ierr); 593 def->W = mats[size]; 594 ierr = PetscObjectReference((PetscObject)mats[size]);CHKERRQ(ierr); 595 if (size > 1) { 596 ierr = MatCreateComposite(comm,size,mats,&nextDef);CHKERRQ(ierr); 597 ierr = MatCompositeSetType(nextDef,MAT_COMPOSITE_MULTIPLICATIVE);CHKERRQ(ierr); 598 } else { 599 nextDef = mats[0]; 600 ierr = PetscObjectReference((PetscObject)mats[0]);CHKERRQ(ierr); 601 } 602 ierr = PetscFree(mats);CHKERRQ(ierr); 603 } else { 604 /* ierr = MatCompositeSetMergeType(def->W,MAT_COMPOSITE_MERGE_LEFT);CHKERRQ(ierr); */ 605 ierr = MatCompositeMerge(def->W);CHKERRQ(ierr); 606 } 607 } else { 608 if (def->nestedlvl < def->maxnestedlvl) { 609 ierr = PetscMalloc1(size,&mats);CHKERRQ(ierr); 610 for (i=0; i<size; i++) { 611 ierr = MatCompositeGetMat(def->Wt,i,&mats[i]);CHKERRQ(ierr); 612 } 613 size -= 1; 614 ierr = MatDestroy(&def->Wt);CHKERRQ(ierr); 615 def->Wt = mats[0]; 616 ierr = PetscObjectReference((PetscObject)mats[0]);CHKERRQ(ierr); 617 if (size > 1) { 618 ierr = MatCreateComposite(comm,size,&mats[1],&nextDef);CHKERRQ(ierr); 619 ierr = MatCompositeSetType(nextDef,MAT_COMPOSITE_MULTIPLICATIVE);CHKERRQ(ierr); 620 } else { 621 nextDef = mats[1]; 622 ierr = PetscObjectReference((PetscObject)mats[1]);CHKERRQ(ierr); 623 } 624 ierr = PetscFree(mats);CHKERRQ(ierr); 625 } else { 626 /* ierr = MatCompositeSetMergeType(def->W,MAT_COMPOSITE_MERGE_LEFT);CHKERRQ(ierr); */ 627 ierr = MatCompositeMerge(def->Wt);CHKERRQ(ierr); 628 } 629 } 630 } 631 632 if (transp) { 633 ierr = MatDestroy(&def->W);CHKERRQ(ierr); 634 ierr = MatHermitianTranspose(def->Wt,MAT_INITIAL_MATRIX,&def->W);CHKERRQ(ierr); 635 } 636 637 /* assemble WtA */ 638 if (!def->WtA) { 639 if (def->Wt) { 640 ierr = MatMatMult(def->Wt,Amat,MAT_INITIAL_MATRIX,PETSC_DEFAULT,&def->WtA);CHKERRQ(ierr); 641 } else { 642 #if defined(PETSC_USE_COMPLEX) 643 ierr = MatHermitianTranspose(def->W,MAT_INITIAL_MATRIX,&def->Wt);CHKERRQ(ierr); 644 ierr = MatMatMult(def->W,Amat,MAT_INITIAL_MATRIX,PETSC_DEFAULT,&def->WtA);CHKERRQ(ierr); 645 #else 646 ierr = MatTransposeMatMult(def->W,Amat,MAT_INITIAL_MATRIX,PETSC_DEFAULT,&def->WtA);CHKERRQ(ierr); 647 #endif 648 } 649 } 650 /* setup coarse problem */ 651 if (!def->WtAWinv) { 652 ierr = MatGetSize(def->W,NULL,&m);CHKERRQ(ierr); 653 if (!def->WtAW) { 654 ierr = MatMatMult(def->WtA,def->W,MAT_INITIAL_MATRIX,PETSC_DEFAULT,&def->WtAW);CHKERRQ(ierr); 655 /* TODO create MatInheritOption(Mat,MatOption) */ 656 ierr = MatGetOption(Amat,MAT_SPD,&flgspd);CHKERRQ(ierr); 657 ierr = MatSetOption(def->WtAW,MAT_SPD,flgspd);CHKERRQ(ierr); 658 #if defined(PETSC_USE_DEBUG) 659 /* Check columns of W are not in kernel of A */ 660 PetscReal *norms; 661 ierr = PetscMalloc1(m,&norms);CHKERRQ(ierr); 662 ierr = MatGetColumnNorms(def->WtAW,NORM_INFINITY,norms);CHKERRQ(ierr); 663 for (i=0; i<m; i++) { 664 if (norms[i] < 100*PETSC_MACHINE_EPSILON) { 665 SETERRQ1(comm,PETSC_ERR_SUP,"Column %D of W is in kernel of A.",i); 666 } 667 } 668 ierr = PetscFree(norms);CHKERRQ(ierr); 669 #endif 670 } else { 671 ierr = MatGetOption(def->WtAW,MAT_SPD,&flgspd);CHKERRQ(ierr); 672 } 673 /* TODO use MATINV */ 674 ierr = KSPCreate(comm,&def->WtAWinv);CHKERRQ(ierr); 675 ierr = KSPSetOperators(def->WtAWinv,def->WtAW,def->WtAW);CHKERRQ(ierr); 676 ierr = KSPGetPC(def->WtAWinv,&pcinner);CHKERRQ(ierr); 677 /* Setup KSP and PC */ 678 if (nextDef) { /* next level for multilevel deflation */ 679 innerksp = def->WtAWinv; 680 /* set default KSPtype */ 681 if (!def->ksptype) { 682 def->ksptype = KSPFGMRES; 683 if (flgspd) { /* SPD system */ 684 def->ksptype = KSPFCG; 685 } 686 } 687 ierr = KSPSetType(innerksp,def->ksptype);CHKERRQ(ierr); /* TODO iherit from KSP + tolerances */ 688 ierr = PCSetType(pcinner,PCDEFLATION);CHKERRQ(ierr); /* TODO create coarse preconditinoner M_c = WtMW ? */ 689 ierr = PCDeflationSetSpace(pcinner,nextDef,transp);CHKERRQ(ierr); 690 ierr = PCDeflationSetLvl_Deflation(pcinner,def->nestedlvl+1,def->maxnestedlvl);CHKERRQ(ierr); 691 /* inherit options */ 692 ((PC_Deflation*)(pcinner->data))->ksptype = def->ksptype; 693 ((PC_Deflation*)(pcinner->data))->correct = def->correct; 694 ierr = MatDestroy(&nextDef);CHKERRQ(ierr); 695 } else { /* the last level */ 696 ierr = KSPSetType(def->WtAWinv,KSPPREONLY);CHKERRQ(ierr); 697 ierr = PCSetType(pcinner,PCTELESCOPE);CHKERRQ(ierr); 698 /* ugly hack to not have overwritten PCTELESCOPE */ 699 if (prefix) { 700 ierr = KSPSetOptionsPrefix(def->WtAWinv,prefix);CHKERRQ(ierr); 701 } 702 ierr = KSPAppendOptionsPrefix(def->WtAWinv,"tel_");CHKERRQ(ierr); 703 ierr = PCSetFromOptions(pcinner);CHKERRQ(ierr); 704 /* Reduction factor choice */ 705 red = def->reductionfact; 706 if (red < 0) { 707 ierr = MPI_Comm_size(comm,&commsize);CHKERRQ(ierr); 708 red = ceil((float)commsize/ceil((float)m/commsize)); 709 ierr = PetscObjectTypeCompareAny((PetscObject)(def->WtAW),&match,MATSEQDENSE,MATMPIDENSE,MATDENSE,"");CHKERRQ(ierr); 710 if (match) red = commsize; 711 ierr = PetscInfo1(pc,"Auto choosing reduction factor %D\n",red);CHKERRQ(ierr); /* TODO add level? */ 712 } 713 ierr = PCTelescopeSetReductionFactor(pcinner,red);CHKERRQ(ierr); 714 ierr = PCSetUp(pcinner);CHKERRQ(ierr); 715 ierr = PCTelescopeGetKSP(pcinner,&innerksp);CHKERRQ(ierr); 716 if (innerksp) { 717 ierr = KSPGetPC(innerksp,&pcinner);CHKERRQ(ierr); 718 /* TODO Cholesky if flgspd? */ 719 ierr = PCSetType(pcinner,PCLU);CHKERRQ(ierr); 720 //TODO remove explicit matSolverPackage 721 if (commsize == red) { 722 ierr = PCFactorSetMatSolverType(pcinner,MATSOLVERSUPERLU);CHKERRQ(ierr); 723 } else { 724 ierr = PCFactorSetMatSolverType(pcinner,MATSOLVERSUPERLU_DIST);CHKERRQ(ierr); 725 } 726 } 727 } 728 729 if (innerksp) { 730 /* TODO use def_[lvl]_ if lvl > 0? */ 731 if (prefix) { 732 ierr = KSPSetOptionsPrefix(innerksp,prefix);CHKERRQ(ierr); 733 } 734 ierr = KSPAppendOptionsPrefix(innerksp,"def_");CHKERRQ(ierr); 735 ierr = KSPSetFromOptions(innerksp);CHKERRQ(ierr); 736 ierr = KSPSetUp(innerksp);CHKERRQ(ierr); 737 } 738 } 739 ierr = KSPSetFromOptions(def->WtAWinv);CHKERRQ(ierr); 740 ierr = KSPSetUp(def->WtAWinv);CHKERRQ(ierr); 741 742 if (!def->pc) { 743 ierr = PCCreate(comm,&def->pc);CHKERRQ(ierr); 744 ierr = PCSetOperators(def->pc,Amat,Amat);CHKERRQ(ierr); 745 ierr = PCSetType(def->pc,PCNONE);CHKERRQ(ierr); 746 if (prefix) { 747 ierr = PCSetOptionsPrefix(def->pc,prefix);CHKERRQ(ierr); 748 } 749 ierr = PCAppendOptionsPrefix(def->pc,"def_pc_");CHKERRQ(ierr); 750 ierr = PCSetFromOptions(def->pc);CHKERRQ(ierr); 751 ierr = PCSetUp(def->pc);CHKERRQ(ierr); 752 } 753 754 /* create work vecs */ 755 ierr = MatCreateVecs(Amat,NULL,&def->work);CHKERRQ(ierr); 756 ierr = KSPCreateVecs(def->WtAWinv,2,&def->workcoarse,0,NULL);CHKERRQ(ierr); 757 PetscFunctionReturn(0); 758 } 759 760 static PetscErrorCode PCReset_Deflation(PC pc) 761 { 762 PC_Deflation *def = (PC_Deflation*)pc->data; 763 PetscErrorCode ierr; 764 765 PetscFunctionBegin; 766 ierr = VecDestroy(&def->work);CHKERRQ(ierr); 767 ierr = VecDestroyVecs(2,&def->workcoarse);CHKERRQ(ierr); 768 ierr = MatDestroy(&def->W);CHKERRQ(ierr); 769 ierr = MatDestroy(&def->Wt);CHKERRQ(ierr); 770 ierr = MatDestroy(&def->WtA);CHKERRQ(ierr); 771 ierr = MatDestroy(&def->WtAW);CHKERRQ(ierr); 772 ierr = KSPDestroy(&def->WtAWinv);CHKERRQ(ierr); 773 ierr = PCDestroy(&def->pc);CHKERRQ(ierr); 774 PetscFunctionReturn(0); 775 } 776 777 /* 778 PCDestroy_Deflation - Destroys the private context for the Deflation preconditioner 779 that was created with PCCreate_Deflation(). 780 781 Input Parameter: 782 . pc - the preconditioner context 783 784 Application Interface Routine: PCDestroy() 785 */ 786 static PetscErrorCode PCDestroy_Deflation(PC pc) 787 { 788 PetscErrorCode ierr; 789 790 PetscFunctionBegin; 791 ierr = PCReset_Deflation(pc);CHKERRQ(ierr); 792 ierr = PetscFree(pc->data);CHKERRQ(ierr); 793 PetscFunctionReturn(0); 794 } 795 796 static PetscErrorCode PCView_Deflation(PC pc,PetscViewer viewer) 797 { 798 PC_Deflation *def = (PC_Deflation*)pc->data; 799 PetscInt its; 800 PetscBool iascii; 801 PetscErrorCode ierr; 802 803 PetscFunctionBegin; 804 ierr = PetscObjectTypeCompare((PetscObject)viewer,PETSCVIEWERASCII,&iascii);CHKERRQ(ierr); 805 if (iascii) { 806 if (def->correct) { 807 ierr = PetscViewerASCIIPrintf(viewer,"using CP correction, factor = %g+%gi\n", 808 (double)PetscRealPart(def->correctfact), 809 (double)PetscImaginaryPart(def->correctfact));CHKERRQ(ierr); 810 } 811 if (!def->nestedlvl) { 812 ierr = PetscViewerASCIIPrintf(viewer,"deflation space type: %s\n",PCDeflationSpaceTypes[def->spacetype]);CHKERRQ(ierr); 813 } 814 815 ierr = PetscViewerASCIIPrintf(viewer,"--- Additional PC:\n");CHKERRQ(ierr); 816 ierr = PetscViewerASCIIPushTab(viewer);CHKERRQ(ierr); 817 ierr = PCView(def->pc,viewer);CHKERRQ(ierr); 818 ierr = PetscViewerASCIIPopTab(viewer);CHKERRQ(ierr); 819 820 ierr = PetscViewerASCIIPrintf(viewer,"--- Coarse problem solver:\n");CHKERRQ(ierr); 821 ierr = PetscViewerASCIIPushTab(viewer);CHKERRQ(ierr); 822 ierr = KSPGetTotalIterations(def->WtAWinv,&its);CHKERRQ(ierr); 823 ierr = PetscViewerASCIIPrintf(viewer,"total number of iterations: %D\n",its);CHKERRQ(ierr); 824 ierr = KSPView(def->WtAWinv,viewer);CHKERRQ(ierr); 825 ierr = PetscViewerASCIIPopTab(viewer);CHKERRQ(ierr); 826 } 827 PetscFunctionReturn(0); 828 } 829 830 static PetscErrorCode PCSetFromOptions_Deflation(PetscOptionItems *PetscOptionsObject,PC pc) 831 { 832 PC_Deflation *def = (PC_Deflation*)pc->data; 833 PetscErrorCode ierr; 834 835 PetscFunctionBegin; 836 ierr = PetscOptionsHead(PetscOptionsObject,"Deflation options");CHKERRQ(ierr); 837 ierr = PetscOptionsBool("-pc_deflation_init_only","Use only initialization step - Initdef","PCDeflationSetInitOnly",def->init,&def->init,NULL);CHKERRQ(ierr); 838 ierr = PetscOptionsInt("-pc_deflation_max_lvl","Maximum of deflation levels","PCDeflationSetMaxLvl",def->maxnestedlvl,&def->maxnestedlvl,NULL);CHKERRQ(ierr); 839 ierr = PetscOptionsInt("-pc_deflation_reduction_factor","Reduction factor for coarse problem solution using PCTELESCOPE","PCDeflationSetReductionFactor",def->reductionfact,&def->reductionfact,NULL);CHKERRQ(ierr); 840 ierr = PetscOptionsBool("-pc_deflation_correction","Add coarse problem correction Q to P","PCDeflationSetCorrectionFactor",def->correct,&def->correct,NULL);CHKERRQ(ierr); 841 ierr = PetscOptionsScalar("-pc_deflation_correction_factor","Set multiple of Q to use as coarse problem correction","PCDeflationSetCorrectionFactor",def->correctfact,&def->correctfact,NULL);CHKERRQ(ierr); 842 ierr = PetscOptionsEnum("-pc_deflation_compute_space","Compute deflation space","PCDeflationSetSpace",PCDeflationSpaceTypes,(PetscEnum)def->spacetype,(PetscEnum*)&def->spacetype,NULL);CHKERRQ(ierr); 843 ierr = PetscOptionsInt("-pc_deflation_compute_space_size","Set size of the deflation space to compute","PCDeflationSetSpace",def->spacesize,&def->spacesize,NULL);CHKERRQ(ierr); 844 ierr = PetscOptionsBool("-pc_deflation_space_extend","Extend deflation space instead of truncating (wavelets)","PCDeflation",def->extendsp,&def->extendsp,NULL);CHKERRQ(ierr); 845 //TODO add set function and fix manpages 846 ierr = PetscOptionsTail();CHKERRQ(ierr); 847 PetscFunctionReturn(0); 848 } 849 850 /*MC 851 PCDEFLATION - Deflation preconditioner shifts part of the spectrum to zero (deflates) 852 or to a predefined value 853 854 Options Database Key: 855 + -pc_deflation_type <init,pre,post> - selects approach to deflation (default: pre) 856 - -pc_jacobi_abs - use the absolute value of the diagonal entry 857 858 Level: beginner 859 860 Notes: 861 todo 862 863 .seealso: PCCreate(), PCSetType(), PCType (for list of available types), PC, 864 PCDeflationSetType(), PCDeflationSetSpace() 865 M*/ 866 867 PETSC_EXTERN PetscErrorCode PCCreate_Deflation(PC pc) 868 { 869 PC_Deflation *def; 870 PetscErrorCode ierr; 871 872 PetscFunctionBegin; 873 ierr = PetscNewLog(pc,&def);CHKERRQ(ierr); 874 pc->data = (void*)def; 875 876 def->init = PETSC_FALSE; 877 def->correct = PETSC_FALSE; 878 def->correctfact = 1.0; 879 def->reductionfact = -1; 880 def->spacetype = PC_DEFLATION_SPACE_HAAR; 881 def->spacesize = 1; 882 def->extendsp = PETSC_FALSE; 883 def->nestedlvl = 0; 884 def->maxnestedlvl = 0; 885 886 pc->ops->apply = PCApply_Deflation; 887 pc->ops->presolve = PCPreSolve_Deflation; 888 pc->ops->setup = PCSetUp_Deflation; 889 pc->ops->reset = PCReset_Deflation; 890 pc->ops->destroy = PCDestroy_Deflation; 891 pc->ops->setfromoptions = PCSetFromOptions_Deflation; 892 pc->ops->view = PCView_Deflation; 893 894 ierr = PetscObjectComposeFunction((PetscObject)pc,"PCDeflationSetInitOnly_C",PCDeflationSetInitOnly_Deflation);CHKERRQ(ierr); 895 ierr = PetscObjectComposeFunction((PetscObject)pc,"PCDeflationSetLvl_C",PCDeflationSetLvl_Deflation);CHKERRQ(ierr); 896 ierr = PetscObjectComposeFunction((PetscObject)pc,"PCDeflationSetReductionFactor_C",PCDeflationSetReductionFactor_Deflation);CHKERRQ(ierr); 897 ierr = PetscObjectComposeFunction((PetscObject)pc,"PCDeflationSetCorrectionFactor_C",PCDeflationSetCorrectionFactor_Deflation);CHKERRQ(ierr); 898 ierr = PetscObjectComposeFunction((PetscObject)pc,"PCDeflationSetSpaceToCompute_C",PCDeflationSetSpaceToCompute_Deflation);CHKERRQ(ierr); 899 ierr = PetscObjectComposeFunction((PetscObject)pc,"PCDeflationSetSpace_C",PCDeflationSetSpace_Deflation);CHKERRQ(ierr); 900 ierr = PetscObjectComposeFunction((PetscObject)pc,"PCDeflationSetProjectionNullSpaceMat_C",PCDeflationSetProjectionNullSpaceMat_Deflation);CHKERRQ(ierr); 901 ierr = PetscObjectComposeFunction((PetscObject)pc,"PCDeflationSetCoarseMat_C",PCDeflationSetCoarseMat_Deflation);CHKERRQ(ierr); 902 ierr = PetscObjectComposeFunction((PetscObject)pc,"PCDeflationGetCoarseKSP_C",PCDeflationGetCoarseKSP_Deflation);CHKERRQ(ierr); 903 ierr = PetscObjectComposeFunction((PetscObject)pc,"PCDeflationSetCoarseKSP_C",PCDeflationSetCoarseKSP_Deflation);CHKERRQ(ierr); 904 ierr = PetscObjectComposeFunction((PetscObject)pc,"PCDeflationGetPC_C",PCDeflationGetPC_Deflation);CHKERRQ(ierr); 905 ierr = PetscObjectComposeFunction((PetscObject)pc,"PCDeflationSetPC_C",PCDeflationSetPC_Deflation);CHKERRQ(ierr); 906 PetscFunctionReturn(0); 907 } 908 909