1a2fc1e05SToby Isaac 2a2fc1e05SToby Isaac /* 3a2fc1e05SToby Isaac Defines a direct QR factorization preconditioner for any Mat implementation 4a2fc1e05SToby Isaac Note: this need not be considered a preconditioner since it supplies 5a2fc1e05SToby Isaac a direct solver. 6a2fc1e05SToby Isaac */ 7a2fc1e05SToby Isaac #include <../src/ksp/pc/impls/factor/qr/qr.h> /*I "petscpc.h" I*/ 8a2fc1e05SToby Isaac 9a2fc1e05SToby Isaac static PetscErrorCode PCSetUp_QR(PC pc) 10a2fc1e05SToby Isaac { 11a2fc1e05SToby Isaac PC_QR *dir = (PC_QR*)pc->data; 12a2fc1e05SToby Isaac MatSolverType stype; 13a2fc1e05SToby Isaac MatFactorError err; 14a2fc1e05SToby Isaac 15a2fc1e05SToby Isaac PetscFunctionBegin; 16a2fc1e05SToby Isaac pc->failedreason = PC_NOERROR; 17a2fc1e05SToby Isaac if (dir->hdr.reusefill && pc->setupcalled) ((PC_Factor*)dir)->info.fill = dir->hdr.actualfill; 18a2fc1e05SToby Isaac 19*9566063dSJacob Faibussowitsch PetscCall(MatSetErrorIfFailure(pc->pmat,pc->erroriffailure)); 20a2fc1e05SToby Isaac if (dir->hdr.inplace) { 21a2fc1e05SToby Isaac MatFactorType ftype; 22a2fc1e05SToby Isaac 23*9566063dSJacob Faibussowitsch PetscCall(MatGetFactorType(pc->pmat, &ftype)); 24a2fc1e05SToby Isaac if (ftype == MAT_FACTOR_NONE) { 25*9566063dSJacob Faibussowitsch PetscCall(MatQRFactor(pc->pmat,dir->col,&((PC_Factor*)dir)->info)); 26*9566063dSJacob Faibussowitsch PetscCall(MatFactorGetError(pc->pmat,&err)); 27a2fc1e05SToby Isaac if (err) { /* Factor() fails */ 28a2fc1e05SToby Isaac pc->failedreason = (PCFailedReason)err; 29a2fc1e05SToby Isaac PetscFunctionReturn(0); 30a2fc1e05SToby Isaac } 31a2fc1e05SToby Isaac } 32a2fc1e05SToby Isaac ((PC_Factor*)dir)->fact = pc->pmat; 33a2fc1e05SToby Isaac } else { 34a2fc1e05SToby Isaac MatInfo info; 35a2fc1e05SToby Isaac 36a2fc1e05SToby Isaac if (!pc->setupcalled) { 37a2fc1e05SToby Isaac if (!((PC_Factor*)dir)->fact) { 38*9566063dSJacob Faibussowitsch PetscCall(MatGetFactor(pc->pmat,((PC_Factor*)dir)->solvertype,MAT_FACTOR_QR,&((PC_Factor*)dir)->fact)); 39*9566063dSJacob Faibussowitsch PetscCall(PetscLogObjectParent((PetscObject)pc,(PetscObject)((PC_Factor*)dir)->fact)); 40a2fc1e05SToby Isaac } 41*9566063dSJacob Faibussowitsch PetscCall(MatQRFactorSymbolic(((PC_Factor*)dir)->fact,pc->pmat,dir->col,&((PC_Factor*)dir)->info)); 42*9566063dSJacob Faibussowitsch PetscCall(MatGetInfo(((PC_Factor*)dir)->fact,MAT_LOCAL,&info)); 43a2fc1e05SToby Isaac dir->hdr.actualfill = info.fill_ratio_needed; 44a2fc1e05SToby Isaac } else if (pc->flag != SAME_NONZERO_PATTERN) { 45*9566063dSJacob Faibussowitsch PetscCall(MatQRFactorSymbolic(((PC_Factor*)dir)->fact,pc->pmat,dir->col,&((PC_Factor*)dir)->info)); 46*9566063dSJacob Faibussowitsch PetscCall(MatGetInfo(((PC_Factor*)dir)->fact,MAT_LOCAL,&info)); 47a2fc1e05SToby Isaac dir->hdr.actualfill = info.fill_ratio_needed; 48a2fc1e05SToby Isaac } else { 49*9566063dSJacob Faibussowitsch PetscCall(MatFactorGetError(((PC_Factor*)dir)->fact,&err)); 50a2fc1e05SToby Isaac } 51*9566063dSJacob Faibussowitsch PetscCall(MatFactorGetError(((PC_Factor*)dir)->fact,&err)); 52a2fc1e05SToby Isaac if (err) { /* FactorSymbolic() fails */ 53a2fc1e05SToby Isaac pc->failedreason = (PCFailedReason)err; 54a2fc1e05SToby Isaac PetscFunctionReturn(0); 55a2fc1e05SToby Isaac } 56a2fc1e05SToby Isaac 57*9566063dSJacob Faibussowitsch PetscCall(MatQRFactorNumeric(((PC_Factor*)dir)->fact,pc->pmat,&((PC_Factor*)dir)->info)); 58*9566063dSJacob Faibussowitsch PetscCall(MatFactorGetError(((PC_Factor*)dir)->fact,&err)); 59a2fc1e05SToby Isaac if (err) { /* FactorNumeric() fails */ 60a2fc1e05SToby Isaac pc->failedreason = (PCFailedReason)err; 61a2fc1e05SToby Isaac } 62a2fc1e05SToby Isaac } 63a2fc1e05SToby Isaac 64*9566063dSJacob Faibussowitsch PetscCall(PCFactorGetMatSolverType(pc,&stype)); 65a2fc1e05SToby Isaac if (!stype) { 66a2fc1e05SToby Isaac MatSolverType solverpackage; 67*9566063dSJacob Faibussowitsch PetscCall(MatFactorGetSolverType(((PC_Factor*)dir)->fact,&solverpackage)); 68*9566063dSJacob Faibussowitsch PetscCall(PCFactorSetMatSolverType(pc,solverpackage)); 69a2fc1e05SToby Isaac } 70a2fc1e05SToby Isaac PetscFunctionReturn(0); 71a2fc1e05SToby Isaac } 72a2fc1e05SToby Isaac 73a2fc1e05SToby Isaac static PetscErrorCode PCReset_QR(PC pc) 74a2fc1e05SToby Isaac { 75a2fc1e05SToby Isaac PC_QR *dir = (PC_QR*)pc->data; 76a2fc1e05SToby Isaac 77a2fc1e05SToby Isaac PetscFunctionBegin; 78*9566063dSJacob Faibussowitsch if (!dir->hdr.inplace && ((PC_Factor*)dir)->fact) PetscCall(MatDestroy(&((PC_Factor*)dir)->fact)); 79*9566063dSJacob Faibussowitsch PetscCall(ISDestroy(&dir->col)); 80a2fc1e05SToby Isaac PetscFunctionReturn(0); 81a2fc1e05SToby Isaac } 82a2fc1e05SToby Isaac 83a2fc1e05SToby Isaac static PetscErrorCode PCDestroy_QR(PC pc) 84a2fc1e05SToby Isaac { 85a2fc1e05SToby Isaac PC_QR *dir = (PC_QR*)pc->data; 86a2fc1e05SToby Isaac 87a2fc1e05SToby Isaac PetscFunctionBegin; 88*9566063dSJacob Faibussowitsch PetscCall(PCReset_QR(pc)); 89*9566063dSJacob Faibussowitsch PetscCall(PetscFree(((PC_Factor*)dir)->ordering)); 90*9566063dSJacob Faibussowitsch PetscCall(PetscFree(((PC_Factor*)dir)->solvertype)); 91*9566063dSJacob Faibussowitsch PetscCall(PetscFree(pc->data)); 92a2fc1e05SToby Isaac PetscFunctionReturn(0); 93a2fc1e05SToby Isaac } 94a2fc1e05SToby Isaac 95a2fc1e05SToby Isaac static PetscErrorCode PCApply_QR(PC pc,Vec x,Vec y) 96a2fc1e05SToby Isaac { 97a2fc1e05SToby Isaac PC_QR *dir = (PC_QR*)pc->data; 98a2fc1e05SToby Isaac Mat fact; 99a2fc1e05SToby Isaac 100a2fc1e05SToby Isaac PetscFunctionBegin; 101a2fc1e05SToby Isaac fact = dir->hdr.inplace ? pc->pmat : ((PC_Factor*)dir)->fact; 102*9566063dSJacob Faibussowitsch PetscCall(MatSolve(fact,x,y)); 103a2fc1e05SToby Isaac PetscFunctionReturn(0); 104a2fc1e05SToby Isaac } 105a2fc1e05SToby Isaac 106a2fc1e05SToby Isaac static PetscErrorCode PCMatApply_QR(PC pc,Mat X,Mat Y) 107a2fc1e05SToby Isaac { 108a2fc1e05SToby Isaac PC_QR *dir = (PC_QR*)pc->data; 109a2fc1e05SToby Isaac Mat fact; 110a2fc1e05SToby Isaac 111a2fc1e05SToby Isaac PetscFunctionBegin; 112a2fc1e05SToby Isaac fact = dir->hdr.inplace ? pc->pmat : ((PC_Factor*)dir)->fact; 113*9566063dSJacob Faibussowitsch PetscCall(MatMatSolve(fact,X,Y)); 114a2fc1e05SToby Isaac PetscFunctionReturn(0); 115a2fc1e05SToby Isaac } 116a2fc1e05SToby Isaac 117a2fc1e05SToby Isaac static PetscErrorCode PCApplyTranspose_QR(PC pc,Vec x,Vec y) 118a2fc1e05SToby Isaac { 119a2fc1e05SToby Isaac PC_QR *dir = (PC_QR*)pc->data; 120a2fc1e05SToby Isaac Mat fact; 121a2fc1e05SToby Isaac 122a2fc1e05SToby Isaac PetscFunctionBegin; 123a2fc1e05SToby Isaac fact = dir->hdr.inplace ? pc->pmat : ((PC_Factor*)dir)->fact; 124*9566063dSJacob Faibussowitsch PetscCall(MatSolveTranspose(fact,x,y)); 125a2fc1e05SToby Isaac PetscFunctionReturn(0); 126a2fc1e05SToby Isaac } 127a2fc1e05SToby Isaac 128a2fc1e05SToby Isaac /* -----------------------------------------------------------------------------------*/ 129a2fc1e05SToby Isaac 130a2fc1e05SToby Isaac /*MC 131a2fc1e05SToby Isaac PCQR - Uses a direct solver, based on QR factorization, as a preconditioner 132a2fc1e05SToby Isaac 133a2fc1e05SToby Isaac Level: beginner 134a2fc1e05SToby Isaac 135a2fc1e05SToby Isaac Notes: 136a2fc1e05SToby Isaac Usually this will compute an "exact" solution in one iteration and does 137a2fc1e05SToby Isaac not need a Krylov method (i.e. you can use -ksp_type preonly, or 138a2fc1e05SToby Isaac KSPSetType(ksp,KSPPREONLY) for the Krylov method 139a2fc1e05SToby Isaac 140a2fc1e05SToby Isaac .seealso: PCCreate(), PCSetType(), PCType (for list of available types), PC, 141a2fc1e05SToby Isaac PCILU, PCLU, PCCHOLESKY, PCICC, PCFactorSetReuseOrdering(), PCFactorSetReuseFill(), PCFactorGetMatrix(), 142a2fc1e05SToby Isaac PCFactorSetFill(), PCFactorSetUseInPlace(), PCFactorSetMatOrderingType(), PCFactorSetColumnPivot(), 143a2fc1e05SToby Isaac PCFactorSetPivotingInBlocks(),PCFactorSetShiftType(),PCFactorSetShiftAmount() 144a2fc1e05SToby Isaac PCFactorReorderForNonzeroDiagonal() 145a2fc1e05SToby Isaac M*/ 146a2fc1e05SToby Isaac 147a2fc1e05SToby Isaac PETSC_EXTERN PetscErrorCode PCCreate_QR(PC pc) 148a2fc1e05SToby Isaac { 149a2fc1e05SToby Isaac PC_QR *dir; 150a2fc1e05SToby Isaac 151a2fc1e05SToby Isaac PetscFunctionBegin; 152*9566063dSJacob Faibussowitsch PetscCall(PetscNewLog(pc,&dir)); 153a2fc1e05SToby Isaac pc->data = (void*)dir; 154*9566063dSJacob Faibussowitsch PetscCall(PCFactorInitialize(pc, MAT_FACTOR_QR)); 155a2fc1e05SToby Isaac 156a2fc1e05SToby Isaac dir->col = NULL; 157a2fc1e05SToby Isaac pc->ops->reset = PCReset_QR; 158a2fc1e05SToby Isaac pc->ops->destroy = PCDestroy_QR; 159a2fc1e05SToby Isaac pc->ops->apply = PCApply_QR; 160a2fc1e05SToby Isaac pc->ops->matapply = PCMatApply_QR; 161a2fc1e05SToby Isaac pc->ops->applytranspose = PCApplyTranspose_QR; 162a2fc1e05SToby Isaac pc->ops->setup = PCSetUp_QR; 163a2fc1e05SToby Isaac pc->ops->setfromoptions = PCSetFromOptions_Factor; 164a2fc1e05SToby Isaac pc->ops->view = PCView_Factor; 165a2fc1e05SToby Isaac pc->ops->applyrichardson = NULL; 166a2fc1e05SToby Isaac PetscFunctionReturn(0); 167a2fc1e05SToby Isaac } 168